xref: /freebsd/sys/dev/bwn/if_bwn.c (revision fafb1ee7bdc5d8a7d07cd03b2fb0bbb76f7a9d7c)
1 /*-
2  * Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer,
10  *    without modification.
11  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13  *    redistribution must be conditioned upon including a substantially
14  *    similar Disclaimer requirement for further binary redistribution.
15  *
16  * NO WARRANTY
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27  * THE POSSIBILITY OF SUCH DAMAGES.
28  */
29 
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32 
33 /*
34  * The Broadcom Wireless LAN controller driver.
35  */
36 
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/module.h>
40 #include <sys/kernel.h>
41 #include <sys/endian.h>
42 #include <sys/errno.h>
43 #include <sys/firmware.h>
44 #include <sys/lock.h>
45 #include <sys/mutex.h>
46 #include <machine/bus.h>
47 #include <machine/resource.h>
48 #include <sys/bus.h>
49 #include <sys/rman.h>
50 #include <sys/socket.h>
51 #include <sys/sockio.h>
52 
53 #include <net/ethernet.h>
54 #include <net/if.h>
55 #include <net/if_var.h>
56 #include <net/if_arp.h>
57 #include <net/if_dl.h>
58 #include <net/if_llc.h>
59 #include <net/if_media.h>
60 #include <net/if_types.h>
61 
62 #include <dev/pci/pcivar.h>
63 #include <dev/pci/pcireg.h>
64 #include <dev/siba/siba_ids.h>
65 #include <dev/siba/sibareg.h>
66 #include <dev/siba/sibavar.h>
67 
68 #include <net80211/ieee80211_var.h>
69 #include <net80211/ieee80211_radiotap.h>
70 #include <net80211/ieee80211_regdomain.h>
71 #include <net80211/ieee80211_phy.h>
72 #include <net80211/ieee80211_ratectl.h>
73 
74 #include <dev/bwn/if_bwnreg.h>
75 #include <dev/bwn/if_bwnvar.h>
76 
77 static SYSCTL_NODE(_hw, OID_AUTO, bwn, CTLFLAG_RD, 0,
78     "Broadcom driver parameters");
79 
80 /*
81  * Tunable & sysctl variables.
82  */
83 
84 #ifdef BWN_DEBUG
85 static	int bwn_debug = 0;
86 SYSCTL_INT(_hw_bwn, OID_AUTO, debug, CTLFLAG_RWTUN, &bwn_debug, 0,
87     "Broadcom debugging printfs");
88 enum {
89 	BWN_DEBUG_XMIT		= 0x00000001,	/* basic xmit operation */
90 	BWN_DEBUG_RECV		= 0x00000002,	/* basic recv operation */
91 	BWN_DEBUG_STATE		= 0x00000004,	/* 802.11 state transitions */
92 	BWN_DEBUG_TXPOW		= 0x00000008,	/* tx power processing */
93 	BWN_DEBUG_RESET		= 0x00000010,	/* reset processing */
94 	BWN_DEBUG_OPS		= 0x00000020,	/* bwn_ops processing */
95 	BWN_DEBUG_BEACON	= 0x00000040,	/* beacon handling */
96 	BWN_DEBUG_WATCHDOG	= 0x00000080,	/* watchdog timeout */
97 	BWN_DEBUG_INTR		= 0x00000100,	/* ISR */
98 	BWN_DEBUG_CALIBRATE	= 0x00000200,	/* periodic calibration */
99 	BWN_DEBUG_NODE		= 0x00000400,	/* node management */
100 	BWN_DEBUG_LED		= 0x00000800,	/* led management */
101 	BWN_DEBUG_CMD		= 0x00001000,	/* cmd submission */
102 	BWN_DEBUG_LO		= 0x00002000,	/* LO */
103 	BWN_DEBUG_FW		= 0x00004000,	/* firmware */
104 	BWN_DEBUG_WME		= 0x00008000,	/* WME */
105 	BWN_DEBUG_RF		= 0x00010000,	/* RF */
106 	BWN_DEBUG_FATAL		= 0x80000000,	/* fatal errors */
107 	BWN_DEBUG_ANY		= 0xffffffff
108 };
109 #define	DPRINTF(sc, m, fmt, ...) do {			\
110 	if (sc->sc_debug & (m))				\
111 		printf(fmt, __VA_ARGS__);		\
112 } while (0)
113 #else
114 #define	DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
115 #endif
116 
117 static int	bwn_bfp = 0;		/* use "Bad Frames Preemption" */
118 SYSCTL_INT(_hw_bwn, OID_AUTO, bfp, CTLFLAG_RW, &bwn_bfp, 0,
119     "uses Bad Frames Preemption");
120 static int	bwn_bluetooth = 1;
121 SYSCTL_INT(_hw_bwn, OID_AUTO, bluetooth, CTLFLAG_RW, &bwn_bluetooth, 0,
122     "turns on Bluetooth Coexistence");
123 static int	bwn_hwpctl = 0;
124 SYSCTL_INT(_hw_bwn, OID_AUTO, hwpctl, CTLFLAG_RW, &bwn_hwpctl, 0,
125     "uses H/W power control");
126 static int	bwn_msi_disable = 0;		/* MSI disabled  */
127 TUNABLE_INT("hw.bwn.msi_disable", &bwn_msi_disable);
128 static int	bwn_usedma = 1;
129 SYSCTL_INT(_hw_bwn, OID_AUTO, usedma, CTLFLAG_RD, &bwn_usedma, 0,
130     "uses DMA");
131 TUNABLE_INT("hw.bwn.usedma", &bwn_usedma);
132 static int	bwn_wme = 1;
133 SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
134     "uses WME support");
135 
136 static void	bwn_attach_pre(struct bwn_softc *);
137 static int	bwn_attach_post(struct bwn_softc *);
138 static void	bwn_sprom_bugfixes(device_t);
139 static int	bwn_init(struct bwn_softc *);
140 static void	bwn_parent(struct ieee80211com *);
141 static void	bwn_start(struct bwn_softc *);
142 static int	bwn_transmit(struct ieee80211com *, struct mbuf *);
143 static int	bwn_attach_core(struct bwn_mac *);
144 static void	bwn_reset_core(struct bwn_mac *, uint32_t);
145 static int	bwn_phy_getinfo(struct bwn_mac *, int);
146 static int	bwn_chiptest(struct bwn_mac *);
147 static int	bwn_setup_channels(struct bwn_mac *, int, int);
148 static int	bwn_phy_g_attach(struct bwn_mac *);
149 static void	bwn_phy_g_detach(struct bwn_mac *);
150 static void	bwn_phy_g_init_pre(struct bwn_mac *);
151 static int	bwn_phy_g_prepare_hw(struct bwn_mac *);
152 static int	bwn_phy_g_init(struct bwn_mac *);
153 static void	bwn_phy_g_exit(struct bwn_mac *);
154 static uint16_t	bwn_phy_g_read(struct bwn_mac *, uint16_t);
155 static void	bwn_phy_g_write(struct bwn_mac *, uint16_t,
156 		    uint16_t);
157 static uint16_t	bwn_phy_g_rf_read(struct bwn_mac *, uint16_t);
158 static void	bwn_phy_g_rf_write(struct bwn_mac *, uint16_t,
159 		    uint16_t);
160 static int	bwn_phy_g_hwpctl(struct bwn_mac *);
161 static void	bwn_phy_g_rf_onoff(struct bwn_mac *, int);
162 static int	bwn_phy_g_switch_channel(struct bwn_mac *, uint32_t);
163 static uint32_t	bwn_phy_g_get_default_chan(struct bwn_mac *);
164 static void	bwn_phy_g_set_antenna(struct bwn_mac *, int);
165 static int	bwn_phy_g_im(struct bwn_mac *, int);
166 static int	bwn_phy_g_recalc_txpwr(struct bwn_mac *, int);
167 static void	bwn_phy_g_set_txpwr(struct bwn_mac *);
168 static void	bwn_phy_g_task_15s(struct bwn_mac *);
169 static void	bwn_phy_g_task_60s(struct bwn_mac *);
170 static uint16_t	bwn_phy_g_txctl(struct bwn_mac *);
171 static void	bwn_phy_switch_analog(struct bwn_mac *, int);
172 static uint16_t	bwn_shm_read_2(struct bwn_mac *, uint16_t, uint16_t);
173 static void	bwn_shm_write_2(struct bwn_mac *, uint16_t, uint16_t,
174 		    uint16_t);
175 static uint32_t	bwn_shm_read_4(struct bwn_mac *, uint16_t, uint16_t);
176 static void	bwn_shm_write_4(struct bwn_mac *, uint16_t, uint16_t,
177 		    uint32_t);
178 static void	bwn_shm_ctlword(struct bwn_mac *, uint16_t,
179 		    uint16_t);
180 static void	bwn_addchannels(struct ieee80211_channel [], int, int *,
181 		    const struct bwn_channelinfo *, int);
182 static int	bwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
183 		    const struct ieee80211_bpf_params *);
184 static void	bwn_updateslot(struct ieee80211com *);
185 static void	bwn_update_promisc(struct ieee80211com *);
186 static void	bwn_wme_init(struct bwn_mac *);
187 static int	bwn_wme_update(struct ieee80211com *);
188 static void	bwn_wme_clear(struct bwn_softc *);
189 static void	bwn_wme_load(struct bwn_mac *);
190 static void	bwn_wme_loadparams(struct bwn_mac *,
191 		    const struct wmeParams *, uint16_t);
192 static void	bwn_scan_start(struct ieee80211com *);
193 static void	bwn_scan_end(struct ieee80211com *);
194 static void	bwn_set_channel(struct ieee80211com *);
195 static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
196 		    const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
197 		    const uint8_t [IEEE80211_ADDR_LEN],
198 		    const uint8_t [IEEE80211_ADDR_LEN]);
199 static void	bwn_vap_delete(struct ieee80211vap *);
200 static void	bwn_stop(struct bwn_softc *);
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 int	bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
412 		    struct mbuf *);
413 static int	bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
414 static int	bwn_set_txhdr(struct bwn_mac *,
415 		    struct ieee80211_node *, struct mbuf *, struct bwn_txhdr *,
416 		    uint16_t);
417 static void	bwn_plcp_genhdr(struct bwn_plcp4 *, const uint16_t,
418 		    const uint8_t);
419 static uint8_t	bwn_antenna_sanitize(struct bwn_mac *, uint8_t);
420 static uint8_t	bwn_get_fbrate(uint8_t);
421 static int	bwn_phy_shm_tssi_read(struct bwn_mac *, uint16_t);
422 static void	bwn_phy_g_setatt(struct bwn_mac *, int *, int *);
423 static void	bwn_phy_lock(struct bwn_mac *);
424 static void	bwn_phy_unlock(struct bwn_mac *);
425 static void	bwn_rf_lock(struct bwn_mac *);
426 static void	bwn_rf_unlock(struct bwn_mac *);
427 static void	bwn_txpwr(void *, int);
428 static void	bwn_tasks(void *);
429 static void	bwn_task_15s(struct bwn_mac *);
430 static void	bwn_task_30s(struct bwn_mac *);
431 static void	bwn_task_60s(struct bwn_mac *);
432 static int	bwn_plcp_get_ofdmrate(struct bwn_mac *, struct bwn_plcp6 *,
433 		    uint8_t);
434 static int	bwn_plcp_get_cckrate(struct bwn_mac *, struct bwn_plcp6 *);
435 static void	bwn_rx_radiotap(struct bwn_mac *, struct mbuf *,
436 		    const struct bwn_rxhdr4 *, struct bwn_plcp6 *, int,
437 		    int, int);
438 static void	bwn_tsf_read(struct bwn_mac *, uint64_t *);
439 static void	bwn_phy_g_dc_lookup_init(struct bwn_mac *, uint8_t);
440 static void	bwn_set_slot_time(struct bwn_mac *, uint16_t);
441 static void	bwn_watchdog(void *);
442 static void	bwn_dma_stop(struct bwn_mac *);
443 static void	bwn_pio_stop(struct bwn_mac *);
444 static void	bwn_dma_ringstop(struct bwn_dma_ring **);
445 static void	bwn_led_attach(struct bwn_mac *);
446 static void	bwn_led_newstate(struct bwn_mac *, enum ieee80211_state);
447 static void	bwn_led_event(struct bwn_mac *, int);
448 static void	bwn_led_blink_start(struct bwn_mac *, int, int);
449 static void	bwn_led_blink_next(void *);
450 static void	bwn_led_blink_end(void *);
451 static void	bwn_rfswitch(void *);
452 static void	bwn_rf_turnon(struct bwn_mac *);
453 static void	bwn_rf_turnoff(struct bwn_mac *);
454 static void	bwn_phy_lp_init_pre(struct bwn_mac *);
455 static int	bwn_phy_lp_init(struct bwn_mac *);
456 static uint16_t	bwn_phy_lp_read(struct bwn_mac *, uint16_t);
457 static void	bwn_phy_lp_write(struct bwn_mac *, uint16_t, uint16_t);
458 static void	bwn_phy_lp_maskset(struct bwn_mac *, uint16_t, uint16_t,
459 		    uint16_t);
460 static uint16_t	bwn_phy_lp_rf_read(struct bwn_mac *, uint16_t);
461 static void	bwn_phy_lp_rf_write(struct bwn_mac *, uint16_t, uint16_t);
462 static void	bwn_phy_lp_rf_onoff(struct bwn_mac *, int);
463 static int	bwn_phy_lp_switch_channel(struct bwn_mac *, uint32_t);
464 static uint32_t	bwn_phy_lp_get_default_chan(struct bwn_mac *);
465 static void	bwn_phy_lp_set_antenna(struct bwn_mac *, int);
466 static void	bwn_phy_lp_task_60s(struct bwn_mac *);
467 static void	bwn_phy_lp_readsprom(struct bwn_mac *);
468 static void	bwn_phy_lp_bbinit(struct bwn_mac *);
469 static void	bwn_phy_lp_txpctl_init(struct bwn_mac *);
470 static void	bwn_phy_lp_calib(struct bwn_mac *);
471 static void	bwn_phy_lp_switch_analog(struct bwn_mac *, int);
472 static int	bwn_phy_lp_b2062_switch_channel(struct bwn_mac *, uint8_t);
473 static int	bwn_phy_lp_b2063_switch_channel(struct bwn_mac *, uint8_t);
474 static void	bwn_phy_lp_set_anafilter(struct bwn_mac *, uint8_t);
475 static void	bwn_phy_lp_set_gaintbl(struct bwn_mac *, uint32_t);
476 static void	bwn_phy_lp_digflt_save(struct bwn_mac *);
477 static void	bwn_phy_lp_get_txpctlmode(struct bwn_mac *);
478 static void	bwn_phy_lp_set_txpctlmode(struct bwn_mac *, uint8_t);
479 static void	bwn_phy_lp_bugfix(struct bwn_mac *);
480 static void	bwn_phy_lp_digflt_restore(struct bwn_mac *);
481 static void	bwn_phy_lp_tblinit(struct bwn_mac *);
482 static void	bwn_phy_lp_bbinit_r2(struct bwn_mac *);
483 static void	bwn_phy_lp_bbinit_r01(struct bwn_mac *);
484 static void	bwn_phy_lp_b2062_init(struct bwn_mac *);
485 static void	bwn_phy_lp_b2063_init(struct bwn_mac *);
486 static void	bwn_phy_lp_rxcal_r2(struct bwn_mac *);
487 static void	bwn_phy_lp_rccal_r12(struct bwn_mac *);
488 static void	bwn_phy_lp_set_rccap(struct bwn_mac *);
489 static uint32_t	bwn_phy_lp_roundup(uint32_t, uint32_t, uint8_t);
490 static void	bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *);
491 static void	bwn_phy_lp_b2062_vco_calib(struct bwn_mac *);
492 static void	bwn_tab_write_multi(struct bwn_mac *, uint32_t, int,
493 		    const void *);
494 static void	bwn_tab_read_multi(struct bwn_mac *, uint32_t, int, void *);
495 static struct bwn_txgain
496 		bwn_phy_lp_get_txgain(struct bwn_mac *);
497 static uint8_t	bwn_phy_lp_get_bbmult(struct bwn_mac *);
498 static void	bwn_phy_lp_set_txgain(struct bwn_mac *, struct bwn_txgain *);
499 static void	bwn_phy_lp_set_bbmult(struct bwn_mac *, uint8_t);
500 static void	bwn_phy_lp_set_trsw_over(struct bwn_mac *, uint8_t, uint8_t);
501 static void	bwn_phy_lp_set_rxgain(struct bwn_mac *, uint32_t);
502 static void	bwn_phy_lp_set_deaf(struct bwn_mac *, uint8_t);
503 static int	bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *, uint16_t);
504 static void	bwn_phy_lp_clear_deaf(struct bwn_mac *, uint8_t);
505 static void	bwn_phy_lp_tblinit_r01(struct bwn_mac *);
506 static void	bwn_phy_lp_tblinit_r2(struct bwn_mac *);
507 static void	bwn_phy_lp_tblinit_txgain(struct bwn_mac *);
508 static void	bwn_tab_write(struct bwn_mac *, uint32_t, uint32_t);
509 static void	bwn_phy_lp_b2062_tblinit(struct bwn_mac *);
510 static void	bwn_phy_lp_b2063_tblinit(struct bwn_mac *);
511 static int	bwn_phy_lp_loopback(struct bwn_mac *);
512 static void	bwn_phy_lp_set_rxgain_idx(struct bwn_mac *, uint16_t);
513 static void	bwn_phy_lp_ddfs_turnon(struct bwn_mac *, int, int, int, int,
514 		    int);
515 static uint8_t	bwn_phy_lp_rx_iq_est(struct bwn_mac *, uint16_t, uint8_t,
516 		    struct bwn_phy_lp_iq_est *);
517 static void	bwn_phy_lp_ddfs_turnoff(struct bwn_mac *);
518 static uint32_t	bwn_tab_read(struct bwn_mac *, uint32_t);
519 static void	bwn_phy_lp_set_txgain_dac(struct bwn_mac *, uint16_t);
520 static void	bwn_phy_lp_set_txgain_pa(struct bwn_mac *, uint16_t);
521 static void	bwn_phy_lp_set_txgain_override(struct bwn_mac *);
522 static uint16_t	bwn_phy_lp_get_pa_gain(struct bwn_mac *);
523 static uint8_t	bwn_nbits(int32_t);
524 static void	bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *, int, int,
525 		    struct bwn_txgain_entry *);
526 static void	bwn_phy_lp_gaintbl_write(struct bwn_mac *, int,
527 		    struct bwn_txgain_entry);
528 static void	bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *, int,
529 		    struct bwn_txgain_entry);
530 static void	bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *, int,
531 		    struct bwn_txgain_entry);
532 static void	bwn_sysctl_node(struct bwn_softc *);
533 
534 static struct resource_spec bwn_res_spec_legacy[] = {
535 	{ SYS_RES_IRQ,		0,		RF_ACTIVE | RF_SHAREABLE },
536 	{ -1,			0,		0 }
537 };
538 
539 static struct resource_spec bwn_res_spec_msi[] = {
540 	{ SYS_RES_IRQ,		1,		RF_ACTIVE },
541 	{ -1,			0,		0 }
542 };
543 
544 static const struct bwn_channelinfo bwn_chantable_bg = {
545 	.channels = {
546 		{ 2412,  1, 30 }, { 2417,  2, 30 }, { 2422,  3, 30 },
547 		{ 2427,  4, 30 }, { 2432,  5, 30 }, { 2437,  6, 30 },
548 		{ 2442,  7, 30 }, { 2447,  8, 30 }, { 2452,  9, 30 },
549 		{ 2457, 10, 30 }, { 2462, 11, 30 }, { 2467, 12, 30 },
550 		{ 2472, 13, 30 }, { 2484, 14, 30 } },
551 	.nchannels = 14
552 };
553 
554 static const struct bwn_channelinfo bwn_chantable_a = {
555 	.channels = {
556 		{ 5170,  34, 30 }, { 5180,  36, 30 }, { 5190,  38, 30 },
557 		{ 5200,  40, 30 }, { 5210,  42, 30 }, { 5220,  44, 30 },
558 		{ 5230,  46, 30 }, { 5240,  48, 30 }, { 5260,  52, 30 },
559 		{ 5280,  56, 30 }, { 5300,  60, 30 }, { 5320,  64, 30 },
560 		{ 5500, 100, 30 }, { 5520, 104, 30 }, { 5540, 108, 30 },
561 		{ 5560, 112, 30 }, { 5580, 116, 30 }, { 5600, 120, 30 },
562 		{ 5620, 124, 30 }, { 5640, 128, 30 }, { 5660, 132, 30 },
563 		{ 5680, 136, 30 }, { 5700, 140, 30 }, { 5745, 149, 30 },
564 		{ 5765, 153, 30 }, { 5785, 157, 30 }, { 5805, 161, 30 },
565 		{ 5825, 165, 30 }, { 5920, 184, 30 }, { 5940, 188, 30 },
566 		{ 5960, 192, 30 }, { 5980, 196, 30 }, { 6000, 200, 30 },
567 		{ 6020, 204, 30 }, { 6040, 208, 30 }, { 6060, 212, 30 },
568 		{ 6080, 216, 30 } },
569 	.nchannels = 37
570 };
571 
572 static const struct bwn_channelinfo bwn_chantable_n = {
573 	.channels = {
574 		{ 5160,  32, 30 }, { 5170,  34, 30 }, { 5180,  36, 30 },
575 		{ 5190,  38, 30 }, { 5200,  40, 30 }, { 5210,  42, 30 },
576 		{ 5220,  44, 30 }, { 5230,  46, 30 }, { 5240,  48, 30 },
577 		{ 5250,  50, 30 }, { 5260,  52, 30 }, { 5270,  54, 30 },
578 		{ 5280,  56, 30 }, { 5290,  58, 30 }, { 5300,  60, 30 },
579 		{ 5310,  62, 30 }, { 5320,  64, 30 }, { 5330,  66, 30 },
580 		{ 5340,  68, 30 }, { 5350,  70, 30 }, { 5360,  72, 30 },
581 		{ 5370,  74, 30 }, { 5380,  76, 30 }, { 5390,  78, 30 },
582 		{ 5400,  80, 30 }, { 5410,  82, 30 }, { 5420,  84, 30 },
583 		{ 5430,  86, 30 }, { 5440,  88, 30 }, { 5450,  90, 30 },
584 		{ 5460,  92, 30 }, { 5470,  94, 30 }, { 5480,  96, 30 },
585 		{ 5490,  98, 30 }, { 5500, 100, 30 }, { 5510, 102, 30 },
586 		{ 5520, 104, 30 }, { 5530, 106, 30 }, { 5540, 108, 30 },
587 		{ 5550, 110, 30 }, { 5560, 112, 30 }, { 5570, 114, 30 },
588 		{ 5580, 116, 30 }, { 5590, 118, 30 }, { 5600, 120, 30 },
589 		{ 5610, 122, 30 }, { 5620, 124, 30 }, { 5630, 126, 30 },
590 		{ 5640, 128, 30 }, { 5650, 130, 30 }, { 5660, 132, 30 },
591 		{ 5670, 134, 30 }, { 5680, 136, 30 }, { 5690, 138, 30 },
592 		{ 5700, 140, 30 }, { 5710, 142, 30 }, { 5720, 144, 30 },
593 		{ 5725, 145, 30 }, { 5730, 146, 30 }, { 5735, 147, 30 },
594 		{ 5740, 148, 30 }, { 5745, 149, 30 }, { 5750, 150, 30 },
595 		{ 5755, 151, 30 }, { 5760, 152, 30 }, { 5765, 153, 30 },
596 		{ 5770, 154, 30 }, { 5775, 155, 30 }, { 5780, 156, 30 },
597 		{ 5785, 157, 30 }, { 5790, 158, 30 }, { 5795, 159, 30 },
598 		{ 5800, 160, 30 }, { 5805, 161, 30 }, { 5810, 162, 30 },
599 		{ 5815, 163, 30 }, { 5820, 164, 30 }, { 5825, 165, 30 },
600 		{ 5830, 166, 30 }, { 5840, 168, 30 }, { 5850, 170, 30 },
601 		{ 5860, 172, 30 }, { 5870, 174, 30 }, { 5880, 176, 30 },
602 		{ 5890, 178, 30 }, { 5900, 180, 30 }, { 5910, 182, 30 },
603 		{ 5920, 184, 30 }, { 5930, 186, 30 }, { 5940, 188, 30 },
604 		{ 5950, 190, 30 }, { 5960, 192, 30 }, { 5970, 194, 30 },
605 		{ 5980, 196, 30 }, { 5990, 198, 30 }, { 6000, 200, 30 },
606 		{ 6010, 202, 30 }, { 6020, 204, 30 }, { 6030, 206, 30 },
607 		{ 6040, 208, 30 }, { 6050, 210, 30 }, { 6060, 212, 30 },
608 		{ 6070, 214, 30 }, { 6080, 216, 30 }, { 6090, 218, 30 },
609 		{ 6100, 220, 30 }, { 6110, 222, 30 }, { 6120, 224, 30 },
610 		{ 6130, 226, 30 }, { 6140, 228, 30 } },
611 	.nchannels = 110
612 };
613 
614 static const uint8_t bwn_b2063_chantable_data[33][12] = {
615 	{ 0x6f, 0x3c, 0x3c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
616 	{ 0x6f, 0x2c, 0x2c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
617 	{ 0x6f, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
618 	{ 0x6e, 0x1c, 0x1c, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
619 	{ 0x6e, 0xc, 0xc, 0x4, 0x5, 0x5, 0x5, 0x5, 0x77, 0x80, 0x80, 0x70 },
620 	{ 0x6a, 0xc, 0xc, 0, 0x2, 0x5, 0xd, 0xd, 0x77, 0x80, 0x20, 0 },
621 	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x5, 0xd, 0xc, 0x77, 0x80, 0x20, 0 },
622 	{ 0x6a, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x80, 0x20, 0 },
623 	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xc, 0xc, 0x77, 0x70, 0x20, 0 },
624 	{ 0x69, 0xc, 0xc, 0, 0x1, 0x4, 0xb, 0xc, 0x77, 0x70, 0x20, 0 },
625 	{ 0x69, 0xc, 0xc, 0, 0, 0x4, 0xb, 0xb, 0x77, 0x60, 0x20, 0 },
626 	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xb, 0x77, 0x60, 0x20, 0 },
627 	{ 0x69, 0xc, 0xc, 0, 0, 0x3, 0xa, 0xa, 0x77, 0x60, 0x20, 0 },
628 	{ 0x68, 0xc, 0xc, 0, 0, 0x2, 0x9, 0x9, 0x77, 0x60, 0x20, 0 },
629 	{ 0x68, 0xc, 0xc, 0, 0, 0x1, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
630 	{ 0x67, 0xc, 0xc, 0, 0, 0, 0x8, 0x8, 0x77, 0x50, 0x10, 0 },
631 	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x2, 0x1, 0x77, 0x20, 0, 0 },
632 	{ 0x64, 0xc, 0xc, 0, 0, 0, 0x1, 0x1, 0x77, 0x20, 0, 0 },
633 	{ 0x63, 0xc, 0xc, 0, 0, 0, 0x1, 0, 0x77, 0x10, 0, 0 },
634 	{ 0x63, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
635 	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0x10, 0, 0 },
636 	{ 0x62, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
637 	{ 0x61, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
638 	{ 0x60, 0xc, 0xc, 0, 0, 0, 0, 0, 0x77, 0, 0, 0 },
639 	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xe, 0xf, 0xf, 0x77, 0xc0, 0x50, 0 },
640 	{ 0x6e, 0xc, 0xc, 0, 0x9, 0xd, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
641 	{ 0x6e, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xb0, 0x50, 0 },
642 	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xc, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
643 	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xb, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
644 	{ 0x6d, 0xc, 0xc, 0, 0x8, 0xa, 0xf, 0xf, 0x77, 0xa0, 0x40, 0 },
645 	{ 0x6c, 0xc, 0xc, 0, 0x7, 0x9, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
646 	{ 0x6c, 0xc, 0xc, 0, 0x6, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 },
647 	{ 0x6c, 0xc, 0xc, 0, 0x5, 0x8, 0xf, 0xf, 0x77, 0x90, 0x40, 0 }
648 };
649 
650 static const struct bwn_b206x_chan bwn_b2063_chantable[] = {
651 	{ 1, 2412, bwn_b2063_chantable_data[0] },
652 	{ 2, 2417, bwn_b2063_chantable_data[0] },
653 	{ 3, 2422, bwn_b2063_chantable_data[0] },
654 	{ 4, 2427, bwn_b2063_chantable_data[1] },
655 	{ 5, 2432, bwn_b2063_chantable_data[1] },
656 	{ 6, 2437, bwn_b2063_chantable_data[1] },
657 	{ 7, 2442, bwn_b2063_chantable_data[1] },
658 	{ 8, 2447, bwn_b2063_chantable_data[1] },
659 	{ 9, 2452, bwn_b2063_chantable_data[2] },
660 	{ 10, 2457, bwn_b2063_chantable_data[2] },
661 	{ 11, 2462, bwn_b2063_chantable_data[3] },
662 	{ 12, 2467, bwn_b2063_chantable_data[3] },
663 	{ 13, 2472, bwn_b2063_chantable_data[3] },
664 	{ 14, 2484, bwn_b2063_chantable_data[4] },
665 	{ 34, 5170, bwn_b2063_chantable_data[5] },
666 	{ 36, 5180, bwn_b2063_chantable_data[6] },
667 	{ 38, 5190, bwn_b2063_chantable_data[7] },
668 	{ 40, 5200, bwn_b2063_chantable_data[8] },
669 	{ 42, 5210, bwn_b2063_chantable_data[9] },
670 	{ 44, 5220, bwn_b2063_chantable_data[10] },
671 	{ 46, 5230, bwn_b2063_chantable_data[11] },
672 	{ 48, 5240, bwn_b2063_chantable_data[12] },
673 	{ 52, 5260, bwn_b2063_chantable_data[13] },
674 	{ 56, 5280, bwn_b2063_chantable_data[14] },
675 	{ 60, 5300, bwn_b2063_chantable_data[14] },
676 	{ 64, 5320, bwn_b2063_chantable_data[15] },
677 	{ 100, 5500, bwn_b2063_chantable_data[16] },
678 	{ 104, 5520, bwn_b2063_chantable_data[17] },
679 	{ 108, 5540, bwn_b2063_chantable_data[18] },
680 	{ 112, 5560, bwn_b2063_chantable_data[19] },
681 	{ 116, 5580, bwn_b2063_chantable_data[20] },
682 	{ 120, 5600, bwn_b2063_chantable_data[21] },
683 	{ 124, 5620, bwn_b2063_chantable_data[21] },
684 	{ 128, 5640, bwn_b2063_chantable_data[22] },
685 	{ 132, 5660, bwn_b2063_chantable_data[22] },
686 	{ 136, 5680, bwn_b2063_chantable_data[22] },
687 	{ 140, 5700, bwn_b2063_chantable_data[23] },
688 	{ 149, 5745, bwn_b2063_chantable_data[23] },
689 	{ 153, 5765, bwn_b2063_chantable_data[23] },
690 	{ 157, 5785, bwn_b2063_chantable_data[23] },
691 	{ 161, 5805, bwn_b2063_chantable_data[23] },
692 	{ 165, 5825, bwn_b2063_chantable_data[23] },
693 	{ 184, 4920, bwn_b2063_chantable_data[24] },
694 	{ 188, 4940, bwn_b2063_chantable_data[25] },
695 	{ 192, 4960, bwn_b2063_chantable_data[26] },
696 	{ 196, 4980, bwn_b2063_chantable_data[27] },
697 	{ 200, 5000, bwn_b2063_chantable_data[28] },
698 	{ 204, 5020, bwn_b2063_chantable_data[29] },
699 	{ 208, 5040, bwn_b2063_chantable_data[30] },
700 	{ 212, 5060, bwn_b2063_chantable_data[31] },
701 	{ 216, 5080, bwn_b2063_chantable_data[32] }
702 };
703 
704 static const uint8_t bwn_b2062_chantable_data[22][12] = {
705 	{ 0xff, 0xff, 0xb5, 0x1b, 0x24, 0x32, 0x32, 0x88, 0x88, 0, 0, 0 },
706 	{ 0, 0x22, 0x20, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
707 	{ 0, 0x11, 0x10, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
708 	{ 0, 0, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
709 	{ 0, 0x11, 0x20, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
710 	{ 0, 0x11, 0x10, 0x84, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
711 	{ 0, 0x11, 0, 0x83, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
712 	{ 0, 0, 0, 0x63, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
713 	{ 0, 0, 0, 0x62, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
714 	{ 0, 0, 0, 0x30, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
715 	{ 0, 0, 0, 0x20, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
716 	{ 0, 0, 0, 0x10, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
717 	{ 0, 0, 0, 0, 0x3c, 0x77, 0x37, 0xff, 0x88, 0, 0, 0 },
718 	{ 0x55, 0x77, 0x90, 0xf7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
719 	{ 0x44, 0x77, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
720 	{ 0x44, 0x66, 0x80, 0xe7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
721 	{ 0x33, 0x66, 0x70, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
722 	{ 0x22, 0x55, 0x60, 0xd7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
723 	{ 0x22, 0x55, 0x60, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
724 	{ 0x22, 0x44, 0x50, 0xc7, 0x3c, 0x77, 0x35, 0xff, 0xff, 0, 0, 0 },
725 	{ 0x11, 0x44, 0x50, 0xa5, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 },
726 	{ 0, 0x44, 0x40, 0xb6, 0x3c, 0x77, 0x35, 0xff, 0x88, 0, 0, 0 }
727 };
728 
729 static const struct bwn_b206x_chan bwn_b2062_chantable[] = {
730 	{ 1, 2412, bwn_b2062_chantable_data[0] },
731 	{ 2, 2417, bwn_b2062_chantable_data[0] },
732 	{ 3, 2422, bwn_b2062_chantable_data[0] },
733 	{ 4, 2427, bwn_b2062_chantable_data[0] },
734 	{ 5, 2432, bwn_b2062_chantable_data[0] },
735 	{ 6, 2437, bwn_b2062_chantable_data[0] },
736 	{ 7, 2442, bwn_b2062_chantable_data[0] },
737 	{ 8, 2447, bwn_b2062_chantable_data[0] },
738 	{ 9, 2452, bwn_b2062_chantable_data[0] },
739 	{ 10, 2457, bwn_b2062_chantable_data[0] },
740 	{ 11, 2462, bwn_b2062_chantable_data[0] },
741 	{ 12, 2467, bwn_b2062_chantable_data[0] },
742 	{ 13, 2472, bwn_b2062_chantable_data[0] },
743 	{ 14, 2484, bwn_b2062_chantable_data[0] },
744 	{ 34, 5170, bwn_b2062_chantable_data[1] },
745 	{ 38, 5190, bwn_b2062_chantable_data[2] },
746 	{ 42, 5210, bwn_b2062_chantable_data[2] },
747 	{ 46, 5230, bwn_b2062_chantable_data[3] },
748 	{ 36, 5180, bwn_b2062_chantable_data[4] },
749 	{ 40, 5200, bwn_b2062_chantable_data[5] },
750 	{ 44, 5220, bwn_b2062_chantable_data[6] },
751 	{ 48, 5240, bwn_b2062_chantable_data[3] },
752 	{ 52, 5260, bwn_b2062_chantable_data[3] },
753 	{ 56, 5280, bwn_b2062_chantable_data[3] },
754 	{ 60, 5300, bwn_b2062_chantable_data[7] },
755 	{ 64, 5320, bwn_b2062_chantable_data[8] },
756 	{ 100, 5500, bwn_b2062_chantable_data[9] },
757 	{ 104, 5520, bwn_b2062_chantable_data[10] },
758 	{ 108, 5540, bwn_b2062_chantable_data[10] },
759 	{ 112, 5560, bwn_b2062_chantable_data[10] },
760 	{ 116, 5580, bwn_b2062_chantable_data[11] },
761 	{ 120, 5600, bwn_b2062_chantable_data[12] },
762 	{ 124, 5620, bwn_b2062_chantable_data[12] },
763 	{ 128, 5640, bwn_b2062_chantable_data[12] },
764 	{ 132, 5660, bwn_b2062_chantable_data[12] },
765 	{ 136, 5680, bwn_b2062_chantable_data[12] },
766 	{ 140, 5700, bwn_b2062_chantable_data[12] },
767 	{ 149, 5745, bwn_b2062_chantable_data[12] },
768 	{ 153, 5765, bwn_b2062_chantable_data[12] },
769 	{ 157, 5785, bwn_b2062_chantable_data[12] },
770 	{ 161, 5805, bwn_b2062_chantable_data[12] },
771 	{ 165, 5825, bwn_b2062_chantable_data[12] },
772 	{ 184, 4920, bwn_b2062_chantable_data[13] },
773 	{ 188, 4940, bwn_b2062_chantable_data[14] },
774 	{ 192, 4960, bwn_b2062_chantable_data[15] },
775 	{ 196, 4980, bwn_b2062_chantable_data[16] },
776 	{ 200, 5000, bwn_b2062_chantable_data[17] },
777 	{ 204, 5020, bwn_b2062_chantable_data[18] },
778 	{ 208, 5040, bwn_b2062_chantable_data[19] },
779 	{ 212, 5060, bwn_b2062_chantable_data[20] },
780 	{ 216, 5080, bwn_b2062_chantable_data[21] }
781 };
782 
783 /* for LP PHY */
784 static const struct bwn_rxcompco bwn_rxcompco_5354[] = {
785 	{  1, -66, 15 }, {  2, -66, 15 }, {  3, -66, 15 }, {  4, -66, 15 },
786 	{  5, -66, 15 }, {  6, -66, 15 }, {  7, -66, 14 }, {  8, -66, 14 },
787 	{  9, -66, 14 }, { 10, -66, 14 }, { 11, -66, 14 }, { 12, -66, 13 },
788 	{ 13, -66, 13 }, { 14, -66, 13 },
789 };
790 
791 /* for LP PHY */
792 static const struct bwn_rxcompco bwn_rxcompco_r12[] = {
793 	{   1, -64, 13 }, {   2, -64, 13 }, {   3, -64, 13 }, {   4, -64, 13 },
794 	{   5, -64, 12 }, {   6, -64, 12 }, {   7, -64, 12 }, {   8, -64, 12 },
795 	{   9, -64, 12 }, {  10, -64, 11 }, {  11, -64, 11 }, {  12, -64, 11 },
796 	{  13, -64, 11 }, {  14, -64, 10 }, {  34, -62, 24 }, {  38, -62, 24 },
797 	{  42, -62, 24 }, {  46, -62, 23 }, {  36, -62, 24 }, {  40, -62, 24 },
798 	{  44, -62, 23 }, {  48, -62, 23 }, {  52, -62, 23 }, {  56, -62, 22 },
799 	{  60, -62, 22 }, {  64, -62, 22 }, { 100, -62, 16 }, { 104, -62, 16 },
800 	{ 108, -62, 15 }, { 112, -62, 14 }, { 116, -62, 14 }, { 120, -62, 13 },
801 	{ 124, -62, 12 }, { 128, -62, 12 }, { 132, -62, 12 }, { 136, -62, 11 },
802 	{ 140, -62, 10 }, { 149, -61,  9 }, { 153, -61,  9 }, { 157, -61,  9 },
803 	{ 161, -61,  8 }, { 165, -61,  8 }, { 184, -62, 25 }, { 188, -62, 25 },
804 	{ 192, -62, 25 }, { 196, -62, 25 }, { 200, -62, 25 }, { 204, -62, 25 },
805 	{ 208, -62, 25 }, { 212, -62, 25 }, { 216, -62, 26 },
806 };
807 
808 static const struct bwn_rxcompco bwn_rxcompco_r2 = { 0, -64, 0 };
809 
810 static const uint8_t bwn_tab_sigsq_tbl[] = {
811 	0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
812 	0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
813 	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
814 	0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
815 	0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
816 	0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
817 };
818 
819 static const uint8_t bwn_tab_pllfrac_tbl[] = {
820 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
821 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
822 };
823 
824 static const uint16_t bwn_tabl_iqlocal_tbl[] = {
825 	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
826 	0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
827 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
828 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
829 	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
830 	0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
831 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 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, 0x4000, 0x0000, 0x0000,
835 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
836 	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
837 };
838 
839 static const uint16_t bwn_tab_noise_g1[] = BWN_TAB_NOISE_G1;
840 static const uint16_t bwn_tab_noise_g2[] = BWN_TAB_NOISE_G2;
841 static const uint16_t bwn_tab_noisescale_g1[] = BWN_TAB_NOISESCALE_G1;
842 static const uint16_t bwn_tab_noisescale_g2[] = BWN_TAB_NOISESCALE_G2;
843 static const uint16_t bwn_tab_noisescale_g3[] = BWN_TAB_NOISESCALE_G3;
844 const uint8_t bwn_bitrev_table[256] = BWN_BITREV_TABLE;
845 
846 #define	VENDOR_LED_ACT(vendor)				\
847 {							\
848 	.vid = PCI_VENDOR_##vendor,			\
849 	.led_act = { BWN_VENDOR_LED_ACT_##vendor }	\
850 }
851 
852 static const struct {
853 	uint16_t	vid;
854 	uint8_t		led_act[BWN_LED_MAX];
855 } bwn_vendor_led_act[] = {
856 	VENDOR_LED_ACT(COMPAQ),
857 	VENDOR_LED_ACT(ASUSTEK)
858 };
859 
860 static const uint8_t bwn_default_led_act[BWN_LED_MAX] =
861 	{ BWN_VENDOR_LED_ACT_DEFAULT };
862 
863 #undef VENDOR_LED_ACT
864 
865 static const struct {
866 	int		on_dur;
867 	int		off_dur;
868 } bwn_led_duration[109] = {
869 	[0]	= { 400, 100 },
870 	[2]	= { 150, 75 },
871 	[4]	= { 90, 45 },
872 	[11]	= { 66, 34 },
873 	[12]	= { 53, 26 },
874 	[18]	= { 42, 21 },
875 	[22]	= { 35, 17 },
876 	[24]	= { 32, 16 },
877 	[36]	= { 21, 10 },
878 	[48]	= { 16, 8 },
879 	[72]	= { 11, 5 },
880 	[96]	= { 9, 4 },
881 	[108]	= { 7, 3 }
882 };
883 
884 static const uint16_t bwn_wme_shm_offsets[] = {
885 	[0] = BWN_WME_BESTEFFORT,
886 	[1] = BWN_WME_BACKGROUND,
887 	[2] = BWN_WME_VOICE,
888 	[3] = BWN_WME_VIDEO,
889 };
890 
891 static const struct siba_devid bwn_devs[] = {
892 	SIBA_DEV(BROADCOM, 80211, 5, "Revision 5"),
893 	SIBA_DEV(BROADCOM, 80211, 6, "Revision 6"),
894 	SIBA_DEV(BROADCOM, 80211, 7, "Revision 7"),
895 	SIBA_DEV(BROADCOM, 80211, 9, "Revision 9"),
896 	SIBA_DEV(BROADCOM, 80211, 10, "Revision 10"),
897 	SIBA_DEV(BROADCOM, 80211, 11, "Revision 11"),
898 	SIBA_DEV(BROADCOM, 80211, 13, "Revision 13"),
899 	SIBA_DEV(BROADCOM, 80211, 15, "Revision 15"),
900 	SIBA_DEV(BROADCOM, 80211, 16, "Revision 16")
901 };
902 
903 static int
904 bwn_probe(device_t dev)
905 {
906 	int i;
907 
908 	for (i = 0; i < sizeof(bwn_devs) / sizeof(bwn_devs[0]); i++) {
909 		if (siba_get_vendor(dev) == bwn_devs[i].sd_vendor &&
910 		    siba_get_device(dev) == bwn_devs[i].sd_device &&
911 		    siba_get_revid(dev) == bwn_devs[i].sd_rev)
912 			return (BUS_PROBE_DEFAULT);
913 	}
914 
915 	return (ENXIO);
916 }
917 
918 static int
919 bwn_attach(device_t dev)
920 {
921 	struct bwn_mac *mac;
922 	struct bwn_softc *sc = device_get_softc(dev);
923 	int error, i, msic, reg;
924 
925 	sc->sc_dev = dev;
926 #ifdef BWN_DEBUG
927 	sc->sc_debug = bwn_debug;
928 #endif
929 
930 	if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
931 		bwn_attach_pre(sc);
932 		bwn_sprom_bugfixes(dev);
933 		sc->sc_flags |= BWN_FLAG_ATTACHED;
934 	}
935 
936 	if (!TAILQ_EMPTY(&sc->sc_maclist)) {
937 		if (siba_get_pci_device(dev) != 0x4313 &&
938 		    siba_get_pci_device(dev) != 0x431a &&
939 		    siba_get_pci_device(dev) != 0x4321) {
940 			device_printf(sc->sc_dev,
941 			    "skip 802.11 cores\n");
942 			return (ENODEV);
943 		}
944 	}
945 
946 	mac = malloc(sizeof(*mac), M_DEVBUF, M_WAITOK | M_ZERO);
947 	mac->mac_sc = sc;
948 	mac->mac_status = BWN_MAC_STATUS_UNINIT;
949 	if (bwn_bfp != 0)
950 		mac->mac_flags |= BWN_MAC_FLAG_BADFRAME_PREEMP;
951 
952 	TASK_INIT(&mac->mac_hwreset, 0, bwn_hwreset, mac);
953 	TASK_INIT(&mac->mac_intrtask, 0, bwn_intrtask, mac);
954 	TASK_INIT(&mac->mac_txpower, 0, bwn_txpwr, mac);
955 
956 	error = bwn_attach_core(mac);
957 	if (error)
958 		goto fail0;
959 	bwn_led_attach(mac);
960 
961 	device_printf(sc->sc_dev, "WLAN (chipid %#x rev %u) "
962 	    "PHY (analog %d type %d rev %d) RADIO (manuf %#x ver %#x rev %d)\n",
963 	    siba_get_chipid(sc->sc_dev), siba_get_revid(sc->sc_dev),
964 	    mac->mac_phy.analog, mac->mac_phy.type, mac->mac_phy.rev,
965 	    mac->mac_phy.rf_manuf, mac->mac_phy.rf_ver,
966 	    mac->mac_phy.rf_rev);
967 	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
968 		device_printf(sc->sc_dev, "DMA (%d bits)\n",
969 		    mac->mac_method.dma.dmatype);
970 	else
971 		device_printf(sc->sc_dev, "PIO\n");
972 
973 	/*
974 	 * setup PCI resources and interrupt.
975 	 */
976 	if (pci_find_cap(dev, PCIY_EXPRESS, &reg) == 0) {
977 		msic = pci_msi_count(dev);
978 		if (bootverbose)
979 			device_printf(sc->sc_dev, "MSI count : %d\n", msic);
980 	} else
981 		msic = 0;
982 
983 	mac->mac_intr_spec = bwn_res_spec_legacy;
984 	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0) {
985 		if (pci_alloc_msi(dev, &msic) == 0) {
986 			device_printf(sc->sc_dev,
987 			    "Using %d MSI messages\n", msic);
988 			mac->mac_intr_spec = bwn_res_spec_msi;
989 			mac->mac_msi = 1;
990 		}
991 	}
992 
993 	error = bus_alloc_resources(dev, mac->mac_intr_spec,
994 	    mac->mac_res_irq);
995 	if (error) {
996 		device_printf(sc->sc_dev,
997 		    "couldn't allocate IRQ resources (%d)\n", error);
998 		goto fail1;
999 	}
1000 
1001 	if (mac->mac_msi == 0)
1002 		error = bus_setup_intr(dev, mac->mac_res_irq[0],
1003 		    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1004 		    &mac->mac_intrhand[0]);
1005 	else {
1006 		for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1007 			error = bus_setup_intr(dev, mac->mac_res_irq[i],
1008 			    INTR_TYPE_NET | INTR_MPSAFE, bwn_intr, NULL, mac,
1009 			    &mac->mac_intrhand[i]);
1010 			if (error != 0) {
1011 				device_printf(sc->sc_dev,
1012 				    "couldn't setup interrupt (%d)\n", error);
1013 				break;
1014 			}
1015 		}
1016 	}
1017 
1018 	TAILQ_INSERT_TAIL(&sc->sc_maclist, mac, mac_list);
1019 
1020 	/*
1021 	 * calls attach-post routine
1022 	 */
1023 	if ((sc->sc_flags & BWN_FLAG_ATTACHED) != 0)
1024 		bwn_attach_post(sc);
1025 
1026 	return (0);
1027 fail1:
1028 	if (msic == BWN_MSI_MESSAGES && bwn_msi_disable == 0)
1029 		pci_release_msi(dev);
1030 fail0:
1031 	free(mac, M_DEVBUF);
1032 	return (error);
1033 }
1034 
1035 static int
1036 bwn_is_valid_ether_addr(uint8_t *addr)
1037 {
1038 	char zero_addr[6] = { 0, 0, 0, 0, 0, 0 };
1039 
1040 	if ((addr[0] & 1) || (!bcmp(addr, zero_addr, ETHER_ADDR_LEN)))
1041 		return (FALSE);
1042 
1043 	return (TRUE);
1044 }
1045 
1046 static int
1047 bwn_attach_post(struct bwn_softc *sc)
1048 {
1049 	struct ieee80211com *ic = &sc->sc_ic;
1050 
1051 	ic->ic_softc = sc;
1052 	ic->ic_name = device_get_nameunit(sc->sc_dev);
1053 	/* XXX not right but it's not used anywhere important */
1054 	ic->ic_phytype = IEEE80211_T_OFDM;
1055 	ic->ic_opmode = IEEE80211_M_STA;
1056 	ic->ic_caps =
1057 		  IEEE80211_C_STA		/* station mode supported */
1058 		| IEEE80211_C_MONITOR		/* monitor mode */
1059 		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
1060 		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
1061 		| IEEE80211_C_SHSLOT		/* short slot time supported */
1062 		| IEEE80211_C_WME		/* WME/WMM supported */
1063 		| IEEE80211_C_WPA		/* capable of WPA1+WPA2 */
1064 		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
1065 		| IEEE80211_C_TXPMGT		/* capable of txpow mgt */
1066 		;
1067 
1068 	ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS;	/* s/w bmiss */
1069 
1070 	IEEE80211_ADDR_COPY(ic->ic_macaddr,
1071 	    bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ?
1072 	    siba_sprom_get_mac_80211a(sc->sc_dev) :
1073 	    siba_sprom_get_mac_80211bg(sc->sc_dev));
1074 
1075 	/* call MI attach routine. */
1076 	ieee80211_ifattach(ic);
1077 
1078 	ic->ic_headroom = sizeof(struct bwn_txhdr);
1079 
1080 	/* override default methods */
1081 	ic->ic_raw_xmit = bwn_raw_xmit;
1082 	ic->ic_updateslot = bwn_updateslot;
1083 	ic->ic_update_promisc = bwn_update_promisc;
1084 	ic->ic_wme.wme_update = bwn_wme_update;
1085 	ic->ic_scan_start = bwn_scan_start;
1086 	ic->ic_scan_end = bwn_scan_end;
1087 	ic->ic_set_channel = bwn_set_channel;
1088 	ic->ic_vap_create = bwn_vap_create;
1089 	ic->ic_vap_delete = bwn_vap_delete;
1090 	ic->ic_transmit = bwn_transmit;
1091 	ic->ic_parent = bwn_parent;
1092 
1093 	ieee80211_radiotap_attach(ic,
1094 	    &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
1095 	    BWN_TX_RADIOTAP_PRESENT,
1096 	    &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th),
1097 	    BWN_RX_RADIOTAP_PRESENT);
1098 
1099 	bwn_sysctl_node(sc);
1100 
1101 	if (bootverbose)
1102 		ieee80211_announce(ic);
1103 	return (0);
1104 }
1105 
1106 static void
1107 bwn_phy_detach(struct bwn_mac *mac)
1108 {
1109 
1110 	if (mac->mac_phy.detach != NULL)
1111 		mac->mac_phy.detach(mac);
1112 }
1113 
1114 static int
1115 bwn_detach(device_t dev)
1116 {
1117 	struct bwn_softc *sc = device_get_softc(dev);
1118 	struct bwn_mac *mac = sc->sc_curmac;
1119 	struct ieee80211com *ic = &sc->sc_ic;
1120 	int i;
1121 
1122 	sc->sc_flags |= BWN_FLAG_INVALID;
1123 
1124 	if (device_is_attached(sc->sc_dev)) {
1125 		BWN_LOCK(sc);
1126 		bwn_stop(sc);
1127 		BWN_UNLOCK(sc);
1128 		bwn_dma_free(mac);
1129 		callout_drain(&sc->sc_led_blink_ch);
1130 		callout_drain(&sc->sc_rfswitch_ch);
1131 		callout_drain(&sc->sc_task_ch);
1132 		callout_drain(&sc->sc_watchdog_ch);
1133 		bwn_phy_detach(mac);
1134 		ieee80211_draintask(ic, &mac->mac_hwreset);
1135 		ieee80211_draintask(ic, &mac->mac_txpower);
1136 		ieee80211_ifdetach(ic);
1137 	}
1138 	taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
1139 	taskqueue_free(sc->sc_tq);
1140 
1141 	for (i = 0; i < BWN_MSI_MESSAGES; i++) {
1142 		if (mac->mac_intrhand[i] != NULL) {
1143 			bus_teardown_intr(dev, mac->mac_res_irq[i],
1144 			    mac->mac_intrhand[i]);
1145 			mac->mac_intrhand[i] = NULL;
1146 		}
1147 	}
1148 	bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
1149 	if (mac->mac_msi != 0)
1150 		pci_release_msi(dev);
1151 	mbufq_drain(&sc->sc_snd);
1152 	BWN_LOCK_DESTROY(sc);
1153 	return (0);
1154 }
1155 
1156 static void
1157 bwn_attach_pre(struct bwn_softc *sc)
1158 {
1159 
1160 	BWN_LOCK_INIT(sc);
1161 	TAILQ_INIT(&sc->sc_maclist);
1162 	callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
1163 	callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
1164 	callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
1165 	mbufq_init(&sc->sc_snd, ifqmaxlen);
1166 	sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
1167 		taskqueue_thread_enqueue, &sc->sc_tq);
1168 	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
1169 		"%s taskq", device_get_nameunit(sc->sc_dev));
1170 }
1171 
1172 static void
1173 bwn_sprom_bugfixes(device_t dev)
1174 {
1175 #define	BWN_ISDEV(_vendor, _device, _subvendor, _subdevice)		\
1176 	((siba_get_pci_vendor(dev) == PCI_VENDOR_##_vendor) &&		\
1177 	 (siba_get_pci_device(dev) == _device) &&			\
1178 	 (siba_get_pci_subvendor(dev) == PCI_VENDOR_##_subvendor) &&	\
1179 	 (siba_get_pci_subdevice(dev) == _subdevice))
1180 
1181 	if (siba_get_pci_subvendor(dev) == PCI_VENDOR_APPLE &&
1182 	    siba_get_pci_subdevice(dev) == 0x4e &&
1183 	    siba_get_pci_revid(dev) > 0x40)
1184 		siba_sprom_set_bf_lo(dev,
1185 		    siba_sprom_get_bf_lo(dev) | BWN_BFL_PACTRL);
1186 	if (siba_get_pci_subvendor(dev) == SIBA_BOARDVENDOR_DELL &&
1187 	    siba_get_chipid(dev) == 0x4301 && siba_get_pci_revid(dev) == 0x74)
1188 		siba_sprom_set_bf_lo(dev,
1189 		    siba_sprom_get_bf_lo(dev) | BWN_BFL_BTCOEXIST);
1190 	if (siba_get_type(dev) == SIBA_TYPE_PCI) {
1191 		if (BWN_ISDEV(BROADCOM, 0x4318, ASUSTEK, 0x100f) ||
1192 		    BWN_ISDEV(BROADCOM, 0x4320, DELL, 0x0003) ||
1193 		    BWN_ISDEV(BROADCOM, 0x4320, HP, 0x12f8) ||
1194 		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0013) ||
1195 		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0014) ||
1196 		    BWN_ISDEV(BROADCOM, 0x4320, LINKSYS, 0x0015) ||
1197 		    BWN_ISDEV(BROADCOM, 0x4320, MOTOROLA, 0x7010))
1198 			siba_sprom_set_bf_lo(dev,
1199 			    siba_sprom_get_bf_lo(dev) & ~BWN_BFL_BTCOEXIST);
1200 	}
1201 #undef	BWN_ISDEV
1202 }
1203 
1204 static void
1205 bwn_parent(struct ieee80211com *ic)
1206 {
1207 	struct bwn_softc *sc = ic->ic_softc;
1208 	int startall = 0;
1209 
1210 	BWN_LOCK(sc);
1211 	if (ic->ic_nrunning > 0) {
1212 		if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0) {
1213 			bwn_init(sc);
1214 			startall = 1;
1215 		} else
1216 			bwn_update_promisc(ic);
1217 	} else if (sc->sc_flags & BWN_FLAG_RUNNING)
1218 		bwn_stop(sc);
1219 	BWN_UNLOCK(sc);
1220 
1221 	if (startall)
1222 		ieee80211_start_all(ic);
1223 }
1224 
1225 static int
1226 bwn_transmit(struct ieee80211com *ic, struct mbuf *m)
1227 {
1228 	struct bwn_softc *sc = ic->ic_softc;
1229 	int error;
1230 
1231 	BWN_LOCK(sc);
1232 	if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0) {
1233 		BWN_UNLOCK(sc);
1234 		return (ENXIO);
1235 	}
1236 	error = mbufq_enqueue(&sc->sc_snd, m);
1237 	if (error) {
1238 		BWN_UNLOCK(sc);
1239 		return (error);
1240 	}
1241 	bwn_start(sc);
1242 	BWN_UNLOCK(sc);
1243 	return (0);
1244 }
1245 
1246 static void
1247 bwn_start(struct bwn_softc *sc)
1248 {
1249 	struct bwn_mac *mac = sc->sc_curmac;
1250 	struct ieee80211_frame *wh;
1251 	struct ieee80211_node *ni;
1252 	struct ieee80211_key *k;
1253 	struct mbuf *m;
1254 
1255 	BWN_ASSERT_LOCKED(sc);
1256 
1257 	if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0 || mac == NULL ||
1258 	    mac->mac_status < BWN_MAC_STATUS_STARTED)
1259 		return;
1260 
1261 	while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
1262 		if (bwn_tx_isfull(sc, m))
1263 			break;
1264 		ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
1265 		if (ni == NULL) {
1266 			device_printf(sc->sc_dev, "unexpected NULL ni\n");
1267 			m_freem(m);
1268 			counter_u64_add(sc->sc_ic.ic_oerrors, 1);
1269 			continue;
1270 		}
1271 		wh = mtod(m, struct ieee80211_frame *);
1272 		if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
1273 			k = ieee80211_crypto_encap(ni, m);
1274 			if (k == NULL) {
1275 				if_inc_counter(ni->ni_vap->iv_ifp,
1276 				    IFCOUNTER_OERRORS, 1);
1277 				ieee80211_free_node(ni);
1278 				m_freem(m);
1279 				continue;
1280 			}
1281 		}
1282 		wh = NULL;	/* Catch any invalid use */
1283 		if (bwn_tx_start(sc, ni, m) != 0) {
1284 			if (ni != NULL) {
1285 				if_inc_counter(ni->ni_vap->iv_ifp,
1286 				    IFCOUNTER_OERRORS, 1);
1287 				ieee80211_free_node(ni);
1288 			}
1289 			continue;
1290 		}
1291 		sc->sc_watchdog_timer = 5;
1292 	}
1293 }
1294 
1295 static int
1296 bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
1297 {
1298 	struct bwn_dma_ring *dr;
1299 	struct bwn_mac *mac = sc->sc_curmac;
1300 	struct bwn_pio_txqueue *tq;
1301 	int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1302 
1303 	BWN_ASSERT_LOCKED(sc);
1304 
1305 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
1306 		dr = bwn_dma_select(mac, M_WME_GETAC(m));
1307 		if (dr->dr_stop == 1 ||
1308 		    bwn_dma_freeslot(dr) < BWN_TX_SLOTS_PER_FRAME) {
1309 			dr->dr_stop = 1;
1310 			goto full;
1311 		}
1312 	} else {
1313 		tq = bwn_pio_select(mac, M_WME_GETAC(m));
1314 		if (tq->tq_free == 0 || pktlen > tq->tq_size ||
1315 		    pktlen > (tq->tq_size - tq->tq_used))
1316 			goto full;
1317 	}
1318 	return (0);
1319 full:
1320 	mbufq_prepend(&sc->sc_snd, m);
1321 	return (1);
1322 }
1323 
1324 static int
1325 bwn_tx_start(struct bwn_softc *sc, struct ieee80211_node *ni, struct mbuf *m)
1326 {
1327 	struct bwn_mac *mac = sc->sc_curmac;
1328 	int error;
1329 
1330 	BWN_ASSERT_LOCKED(sc);
1331 
1332 	if (m->m_pkthdr.len < IEEE80211_MIN_LEN || mac == NULL) {
1333 		m_freem(m);
1334 		return (ENXIO);
1335 	}
1336 
1337 	error = (mac->mac_flags & BWN_MAC_FLAG_DMA) ?
1338 	    bwn_dma_tx_start(mac, ni, m) : bwn_pio_tx_start(mac, ni, m);
1339 	if (error) {
1340 		m_freem(m);
1341 		return (error);
1342 	}
1343 	return (0);
1344 }
1345 
1346 static int
1347 bwn_pio_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1348 {
1349 	struct bwn_pio_txpkt *tp;
1350 	struct bwn_pio_txqueue *tq = bwn_pio_select(mac, M_WME_GETAC(m));
1351 	struct bwn_softc *sc = mac->mac_sc;
1352 	struct bwn_txhdr txhdr;
1353 	struct mbuf *m_new;
1354 	uint32_t ctl32;
1355 	int error;
1356 	uint16_t ctl16;
1357 
1358 	BWN_ASSERT_LOCKED(sc);
1359 
1360 	/* XXX TODO send packets after DTIM */
1361 
1362 	KASSERT(!TAILQ_EMPTY(&tq->tq_pktlist), ("%s: fail", __func__));
1363 	tp = TAILQ_FIRST(&tq->tq_pktlist);
1364 	tp->tp_ni = ni;
1365 	tp->tp_m = m;
1366 
1367 	error = bwn_set_txhdr(mac, ni, m, &txhdr, BWN_PIO_COOKIE(tq, tp));
1368 	if (error) {
1369 		device_printf(sc->sc_dev, "tx fail\n");
1370 		return (error);
1371 	}
1372 
1373 	TAILQ_REMOVE(&tq->tq_pktlist, tp, tp_list);
1374 	tq->tq_used += roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
1375 	tq->tq_free--;
1376 
1377 	if (siba_get_revid(sc->sc_dev) >= 8) {
1378 		/*
1379 		 * XXX please removes m_defrag(9)
1380 		 */
1381 		m_new = m_defrag(m, M_NOWAIT);
1382 		if (m_new == NULL) {
1383 			device_printf(sc->sc_dev,
1384 			    "%s: can't defrag TX buffer\n",
1385 			    __func__);
1386 			return (ENOBUFS);
1387 		}
1388 		if (m_new->m_next != NULL)
1389 			device_printf(sc->sc_dev,
1390 			    "TODO: fragmented packets for PIO\n");
1391 		tp->tp_m = m_new;
1392 
1393 		/* send HEADER */
1394 		ctl32 = bwn_pio_write_multi_4(mac, tq,
1395 		    (BWN_PIO_READ_4(mac, tq, BWN_PIO8_TXCTL) |
1396 			BWN_PIO8_TXCTL_FRAMEREADY) & ~BWN_PIO8_TXCTL_EOF,
1397 		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1398 		/* send BODY */
1399 		ctl32 = bwn_pio_write_multi_4(mac, tq, ctl32,
1400 		    mtod(m_new, const void *), m_new->m_pkthdr.len);
1401 		bwn_pio_write_4(mac, tq, BWN_PIO_TXCTL,
1402 		    ctl32 | BWN_PIO8_TXCTL_EOF);
1403 	} else {
1404 		ctl16 = bwn_pio_write_multi_2(mac, tq,
1405 		    (bwn_pio_read_2(mac, tq, BWN_PIO_TXCTL) |
1406 			BWN_PIO_TXCTL_FRAMEREADY) & ~BWN_PIO_TXCTL_EOF,
1407 		    (const uint8_t *)&txhdr, BWN_HDRSIZE(mac));
1408 		ctl16 = bwn_pio_write_mbuf_2(mac, tq, ctl16, m);
1409 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL,
1410 		    ctl16 | BWN_PIO_TXCTL_EOF);
1411 	}
1412 
1413 	return (0);
1414 }
1415 
1416 static struct bwn_pio_txqueue *
1417 bwn_pio_select(struct bwn_mac *mac, uint8_t prio)
1418 {
1419 
1420 	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
1421 		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1422 
1423 	switch (prio) {
1424 	case 0:
1425 		return (&mac->mac_method.pio.wme[WME_AC_BE]);
1426 	case 1:
1427 		return (&mac->mac_method.pio.wme[WME_AC_BK]);
1428 	case 2:
1429 		return (&mac->mac_method.pio.wme[WME_AC_VI]);
1430 	case 3:
1431 		return (&mac->mac_method.pio.wme[WME_AC_VO]);
1432 	}
1433 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
1434 	return (NULL);
1435 }
1436 
1437 static int
1438 bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
1439 {
1440 #define	BWN_GET_TXHDRCACHE(slot)					\
1441 	&(txhdr_cache[(slot / BWN_TX_SLOTS_PER_FRAME) * BWN_HDRSIZE(mac)])
1442 	struct bwn_dma *dma = &mac->mac_method.dma;
1443 	struct bwn_dma_ring *dr = bwn_dma_select(mac, M_WME_GETAC(m));
1444 	struct bwn_dmadesc_generic *desc;
1445 	struct bwn_dmadesc_meta *mt;
1446 	struct bwn_softc *sc = mac->mac_sc;
1447 	uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
1448 	int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
1449 
1450 	BWN_ASSERT_LOCKED(sc);
1451 	KASSERT(!dr->dr_stop, ("%s:%d: fail", __func__, __LINE__));
1452 
1453 	/* XXX send after DTIM */
1454 
1455 	slot = bwn_dma_getslot(dr);
1456 	dr->getdesc(dr, slot, &desc, &mt);
1457 	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_HEADER,
1458 	    ("%s:%d: fail", __func__, __LINE__));
1459 
1460 	error = bwn_set_txhdr(dr->dr_mac, ni, m,
1461 	    (struct bwn_txhdr *)BWN_GET_TXHDRCACHE(slot),
1462 	    BWN_DMA_COOKIE(dr, slot));
1463 	if (error)
1464 		goto fail;
1465 	error = bus_dmamap_load(dr->dr_txring_dtag, mt->mt_dmap,
1466 	    BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
1467 	    &mt->mt_paddr, BUS_DMA_NOWAIT);
1468 	if (error) {
1469 		device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n",
1470 		    __func__, error);
1471 		goto fail;
1472 	}
1473 	bus_dmamap_sync(dr->dr_txring_dtag, mt->mt_dmap,
1474 	    BUS_DMASYNC_PREWRITE);
1475 	dr->setdesc(dr, desc, mt->mt_paddr, BWN_HDRSIZE(mac), 1, 0, 0);
1476 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1477 	    BUS_DMASYNC_PREWRITE);
1478 
1479 	slot = bwn_dma_getslot(dr);
1480 	dr->getdesc(dr, slot, &desc, &mt);
1481 	KASSERT(mt->mt_txtype == BWN_DMADESC_METATYPE_BODY &&
1482 	    mt->mt_islast == 1, ("%s:%d: fail", __func__, __LINE__));
1483 	mt->mt_m = m;
1484 	mt->mt_ni = ni;
1485 
1486 	error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
1487 	    bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1488 	if (error && error != EFBIG) {
1489 		device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n",
1490 		    __func__, error);
1491 		goto fail;
1492 	}
1493 	if (error) {    /* error == EFBIG */
1494 		struct mbuf *m_new;
1495 
1496 		m_new = m_defrag(m, M_NOWAIT);
1497 		if (m_new == NULL) {
1498 			device_printf(sc->sc_dev,
1499 			    "%s: can't defrag TX buffer\n",
1500 			    __func__);
1501 			error = ENOBUFS;
1502 			goto fail;
1503 		} else {
1504 			m = m_new;
1505 		}
1506 
1507 		mt->mt_m = m;
1508 		error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
1509 		    m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
1510 		if (error) {
1511 			device_printf(sc->sc_dev,
1512 			    "%s: can't load TX buffer (2) %d\n",
1513 			    __func__, error);
1514 			goto fail;
1515 		}
1516 	}
1517 	bus_dmamap_sync(dma->txbuf_dtag, mt->mt_dmap, BUS_DMASYNC_PREWRITE);
1518 	dr->setdesc(dr, desc, mt->mt_paddr, m->m_pkthdr.len, 0, 1, 1);
1519 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
1520 	    BUS_DMASYNC_PREWRITE);
1521 
1522 	/* XXX send after DTIM */
1523 
1524 	dr->start_transfer(dr, bwn_dma_nextslot(dr, slot));
1525 	return (0);
1526 fail:
1527 	dr->dr_curslot = backup[0];
1528 	dr->dr_usedslot = backup[1];
1529 	return (error);
1530 #undef BWN_GET_TXHDRCACHE
1531 }
1532 
1533 static void
1534 bwn_watchdog(void *arg)
1535 {
1536 	struct bwn_softc *sc = arg;
1537 
1538 	if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
1539 		device_printf(sc->sc_dev, "device timeout\n");
1540 		counter_u64_add(sc->sc_ic.ic_oerrors, 1);
1541 	}
1542 	callout_schedule(&sc->sc_watchdog_ch, hz);
1543 }
1544 
1545 static int
1546 bwn_attach_core(struct bwn_mac *mac)
1547 {
1548 	struct bwn_softc *sc = mac->mac_sc;
1549 	int error, have_bg = 0, have_a = 0;
1550 	uint32_t high;
1551 
1552 	KASSERT(siba_get_revid(sc->sc_dev) >= 5,
1553 	    ("unsupported revision %d", siba_get_revid(sc->sc_dev)));
1554 
1555 	siba_powerup(sc->sc_dev, 0);
1556 
1557 	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
1558 	bwn_reset_core(mac,
1559 	    (high & BWN_TGSHIGH_HAVE_2GHZ) ? BWN_TGSLOW_SUPPORT_G : 0);
1560 	error = bwn_phy_getinfo(mac, high);
1561 	if (error)
1562 		goto fail;
1563 
1564 	have_a = (high & BWN_TGSHIGH_HAVE_5GHZ) ? 1 : 0;
1565 	have_bg = (high & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1566 	if (siba_get_pci_device(sc->sc_dev) != 0x4312 &&
1567 	    siba_get_pci_device(sc->sc_dev) != 0x4319 &&
1568 	    siba_get_pci_device(sc->sc_dev) != 0x4324) {
1569 		have_a = have_bg = 0;
1570 		if (mac->mac_phy.type == BWN_PHYTYPE_A)
1571 			have_a = 1;
1572 		else if (mac->mac_phy.type == BWN_PHYTYPE_G ||
1573 		    mac->mac_phy.type == BWN_PHYTYPE_N ||
1574 		    mac->mac_phy.type == BWN_PHYTYPE_LP)
1575 			have_bg = 1;
1576 		else
1577 			KASSERT(0 == 1, ("%s: unknown phy type (%d)", __func__,
1578 			    mac->mac_phy.type));
1579 	}
1580 	/* XXX turns off PHY A because it's not supported */
1581 	if (mac->mac_phy.type != BWN_PHYTYPE_LP &&
1582 	    mac->mac_phy.type != BWN_PHYTYPE_N) {
1583 		have_a = 0;
1584 		have_bg = 1;
1585 	}
1586 
1587 	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
1588 		mac->mac_phy.attach = bwn_phy_g_attach;
1589 		mac->mac_phy.detach = bwn_phy_g_detach;
1590 		mac->mac_phy.prepare_hw = bwn_phy_g_prepare_hw;
1591 		mac->mac_phy.init_pre = bwn_phy_g_init_pre;
1592 		mac->mac_phy.init = bwn_phy_g_init;
1593 		mac->mac_phy.exit = bwn_phy_g_exit;
1594 		mac->mac_phy.phy_read = bwn_phy_g_read;
1595 		mac->mac_phy.phy_write = bwn_phy_g_write;
1596 		mac->mac_phy.rf_read = bwn_phy_g_rf_read;
1597 		mac->mac_phy.rf_write = bwn_phy_g_rf_write;
1598 		mac->mac_phy.use_hwpctl = bwn_phy_g_hwpctl;
1599 		mac->mac_phy.rf_onoff = bwn_phy_g_rf_onoff;
1600 		mac->mac_phy.switch_analog = bwn_phy_switch_analog;
1601 		mac->mac_phy.switch_channel = bwn_phy_g_switch_channel;
1602 		mac->mac_phy.get_default_chan = bwn_phy_g_get_default_chan;
1603 		mac->mac_phy.set_antenna = bwn_phy_g_set_antenna;
1604 		mac->mac_phy.set_im = bwn_phy_g_im;
1605 		mac->mac_phy.recalc_txpwr = bwn_phy_g_recalc_txpwr;
1606 		mac->mac_phy.set_txpwr = bwn_phy_g_set_txpwr;
1607 		mac->mac_phy.task_15s = bwn_phy_g_task_15s;
1608 		mac->mac_phy.task_60s = bwn_phy_g_task_60s;
1609 	} else if (mac->mac_phy.type == BWN_PHYTYPE_LP) {
1610 		mac->mac_phy.init_pre = bwn_phy_lp_init_pre;
1611 		mac->mac_phy.init = bwn_phy_lp_init;
1612 		mac->mac_phy.phy_read = bwn_phy_lp_read;
1613 		mac->mac_phy.phy_write = bwn_phy_lp_write;
1614 		mac->mac_phy.phy_maskset = bwn_phy_lp_maskset;
1615 		mac->mac_phy.rf_read = bwn_phy_lp_rf_read;
1616 		mac->mac_phy.rf_write = bwn_phy_lp_rf_write;
1617 		mac->mac_phy.rf_onoff = bwn_phy_lp_rf_onoff;
1618 		mac->mac_phy.switch_analog = bwn_phy_lp_switch_analog;
1619 		mac->mac_phy.switch_channel = bwn_phy_lp_switch_channel;
1620 		mac->mac_phy.get_default_chan = bwn_phy_lp_get_default_chan;
1621 		mac->mac_phy.set_antenna = bwn_phy_lp_set_antenna;
1622 		mac->mac_phy.task_60s = bwn_phy_lp_task_60s;
1623 	} else {
1624 		device_printf(sc->sc_dev, "unsupported PHY type (%d)\n",
1625 		    mac->mac_phy.type);
1626 		error = ENXIO;
1627 		goto fail;
1628 	}
1629 
1630 	mac->mac_phy.gmode = have_bg;
1631 	if (mac->mac_phy.attach != NULL) {
1632 		error = mac->mac_phy.attach(mac);
1633 		if (error) {
1634 			device_printf(sc->sc_dev, "failed\n");
1635 			goto fail;
1636 		}
1637 	}
1638 
1639 	bwn_reset_core(mac, have_bg ? BWN_TGSLOW_SUPPORT_G : 0);
1640 
1641 	error = bwn_chiptest(mac);
1642 	if (error)
1643 		goto fail;
1644 	error = bwn_setup_channels(mac, have_bg, have_a);
1645 	if (error) {
1646 		device_printf(sc->sc_dev, "failed to setup channels\n");
1647 		goto fail;
1648 	}
1649 
1650 	if (sc->sc_curmac == NULL)
1651 		sc->sc_curmac = mac;
1652 
1653 	error = bwn_dma_attach(mac);
1654 	if (error != 0) {
1655 		device_printf(sc->sc_dev, "failed to initialize DMA\n");
1656 		goto fail;
1657 	}
1658 
1659 	mac->mac_phy.switch_analog(mac, 0);
1660 
1661 	siba_dev_down(sc->sc_dev, 0);
1662 fail:
1663 	siba_powerdown(sc->sc_dev);
1664 	return (error);
1665 }
1666 
1667 static void
1668 bwn_reset_core(struct bwn_mac *mac, uint32_t flags)
1669 {
1670 	struct bwn_softc *sc = mac->mac_sc;
1671 	uint32_t low, ctl;
1672 
1673 	flags |= (BWN_TGSLOW_PHYCLOCK_ENABLE | BWN_TGSLOW_PHYRESET);
1674 
1675 	siba_dev_up(sc->sc_dev, flags);
1676 	DELAY(2000);
1677 
1678 	low = (siba_read_4(sc->sc_dev, SIBA_TGSLOW) | SIBA_TGSLOW_FGC) &
1679 	    ~BWN_TGSLOW_PHYRESET;
1680 	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low);
1681 	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1682 	DELAY(1000);
1683 	siba_write_4(sc->sc_dev, SIBA_TGSLOW, low & ~SIBA_TGSLOW_FGC);
1684 	siba_read_4(sc->sc_dev, SIBA_TGSLOW);
1685 	DELAY(1000);
1686 
1687 	if (mac->mac_phy.switch_analog != NULL)
1688 		mac->mac_phy.switch_analog(mac, 1);
1689 
1690 	ctl = BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GMODE;
1691 	if (flags & BWN_TGSLOW_SUPPORT_G)
1692 		ctl |= BWN_MACCTL_GMODE;
1693 	BWN_WRITE_4(mac, BWN_MACCTL, ctl | BWN_MACCTL_IHR_ON);
1694 }
1695 
1696 static int
1697 bwn_phy_getinfo(struct bwn_mac *mac, int tgshigh)
1698 {
1699 	struct bwn_phy *phy = &mac->mac_phy;
1700 	struct bwn_softc *sc = mac->mac_sc;
1701 	uint32_t tmp;
1702 
1703 	/* PHY */
1704 	tmp = BWN_READ_2(mac, BWN_PHYVER);
1705 	phy->gmode = (tgshigh & BWN_TGSHIGH_HAVE_2GHZ) ? 1 : 0;
1706 	phy->rf_on = 1;
1707 	phy->analog = (tmp & BWN_PHYVER_ANALOG) >> 12;
1708 	phy->type = (tmp & BWN_PHYVER_TYPE) >> 8;
1709 	phy->rev = (tmp & BWN_PHYVER_VERSION);
1710 	if ((phy->type == BWN_PHYTYPE_A && phy->rev >= 4) ||
1711 	    (phy->type == BWN_PHYTYPE_B && phy->rev != 2 &&
1712 		phy->rev != 4 && phy->rev != 6 && phy->rev != 7) ||
1713 	    (phy->type == BWN_PHYTYPE_G && phy->rev > 9) ||
1714 	    (phy->type == BWN_PHYTYPE_N && phy->rev > 4) ||
1715 	    (phy->type == BWN_PHYTYPE_LP && phy->rev > 2))
1716 		goto unsupphy;
1717 
1718 	/* RADIO */
1719 	if (siba_get_chipid(sc->sc_dev) == 0x4317) {
1720 		if (siba_get_chiprev(sc->sc_dev) == 0)
1721 			tmp = 0x3205017f;
1722 		else if (siba_get_chiprev(sc->sc_dev) == 1)
1723 			tmp = 0x4205017f;
1724 		else
1725 			tmp = 0x5205017f;
1726 	} else {
1727 		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1728 		tmp = BWN_READ_2(mac, BWN_RFDATALO);
1729 		BWN_WRITE_2(mac, BWN_RFCTL, BWN_RFCTL_ID);
1730 		tmp |= (uint32_t)BWN_READ_2(mac, BWN_RFDATAHI) << 16;
1731 	}
1732 	phy->rf_rev = (tmp & 0xf0000000) >> 28;
1733 	phy->rf_ver = (tmp & 0x0ffff000) >> 12;
1734 	phy->rf_manuf = (tmp & 0x00000fff);
1735 	if (phy->rf_manuf != 0x17f)	/* 0x17f is broadcom */
1736 		goto unsupradio;
1737 	if ((phy->type == BWN_PHYTYPE_A && (phy->rf_ver != 0x2060 ||
1738 	     phy->rf_rev != 1 || phy->rf_manuf != 0x17f)) ||
1739 	    (phy->type == BWN_PHYTYPE_B && (phy->rf_ver & 0xfff0) != 0x2050) ||
1740 	    (phy->type == BWN_PHYTYPE_G && phy->rf_ver != 0x2050) ||
1741 	    (phy->type == BWN_PHYTYPE_N &&
1742 	     phy->rf_ver != 0x2055 && phy->rf_ver != 0x2056) ||
1743 	    (phy->type == BWN_PHYTYPE_LP &&
1744 	     phy->rf_ver != 0x2062 && phy->rf_ver != 0x2063))
1745 		goto unsupradio;
1746 
1747 	return (0);
1748 unsupphy:
1749 	device_printf(sc->sc_dev, "unsupported PHY (type %#x, rev %#x, "
1750 	    "analog %#x)\n",
1751 	    phy->type, phy->rev, phy->analog);
1752 	return (ENXIO);
1753 unsupradio:
1754 	device_printf(sc->sc_dev, "unsupported radio (manuf %#x, ver %#x, "
1755 	    "rev %#x)\n",
1756 	    phy->rf_manuf, phy->rf_ver, phy->rf_rev);
1757 	return (ENXIO);
1758 }
1759 
1760 static int
1761 bwn_chiptest(struct bwn_mac *mac)
1762 {
1763 #define	TESTVAL0	0x55aaaa55
1764 #define	TESTVAL1	0xaa5555aa
1765 	struct bwn_softc *sc = mac->mac_sc;
1766 	uint32_t v, backup;
1767 
1768 	BWN_LOCK(sc);
1769 
1770 	backup = bwn_shm_read_4(mac, BWN_SHARED, 0);
1771 
1772 	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL0);
1773 	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL0)
1774 		goto error;
1775 	bwn_shm_write_4(mac, BWN_SHARED, 0, TESTVAL1);
1776 	if (bwn_shm_read_4(mac, BWN_SHARED, 0) != TESTVAL1)
1777 		goto error;
1778 
1779 	bwn_shm_write_4(mac, BWN_SHARED, 0, backup);
1780 
1781 	if ((siba_get_revid(sc->sc_dev) >= 3) &&
1782 	    (siba_get_revid(sc->sc_dev) <= 10)) {
1783 		BWN_WRITE_2(mac, BWN_TSF_CFP_START, 0xaaaa);
1784 		BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0xccccbbbb);
1785 		if (BWN_READ_2(mac, BWN_TSF_CFP_START_LOW) != 0xbbbb)
1786 			goto error;
1787 		if (BWN_READ_2(mac, BWN_TSF_CFP_START_HIGH) != 0xcccc)
1788 			goto error;
1789 	}
1790 	BWN_WRITE_4(mac, BWN_TSF_CFP_START, 0);
1791 
1792 	v = BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_GMODE;
1793 	if (v != (BWN_MACCTL_GMODE | BWN_MACCTL_IHR_ON))
1794 		goto error;
1795 
1796 	BWN_UNLOCK(sc);
1797 	return (0);
1798 error:
1799 	BWN_UNLOCK(sc);
1800 	device_printf(sc->sc_dev, "failed to validate the chipaccess\n");
1801 	return (ENODEV);
1802 }
1803 
1804 #define	IEEE80211_CHAN_HTG	(IEEE80211_CHAN_HT | IEEE80211_CHAN_G)
1805 #define	IEEE80211_CHAN_HTA	(IEEE80211_CHAN_HT | IEEE80211_CHAN_A)
1806 
1807 static int
1808 bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
1809 {
1810 	struct bwn_softc *sc = mac->mac_sc;
1811 	struct ieee80211com *ic = &sc->sc_ic;
1812 
1813 	memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
1814 	ic->ic_nchans = 0;
1815 
1816 	if (have_bg)
1817 		bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1818 		    &ic->ic_nchans, &bwn_chantable_bg, IEEE80211_CHAN_G);
1819 	if (mac->mac_phy.type == BWN_PHYTYPE_N) {
1820 		if (have_a)
1821 			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1822 			    &ic->ic_nchans, &bwn_chantable_n,
1823 			    IEEE80211_CHAN_HTA);
1824 	} else {
1825 		if (have_a)
1826 			bwn_addchannels(ic->ic_channels, IEEE80211_CHAN_MAX,
1827 			    &ic->ic_nchans, &bwn_chantable_a,
1828 			    IEEE80211_CHAN_A);
1829 	}
1830 
1831 	mac->mac_phy.supports_2ghz = have_bg;
1832 	mac->mac_phy.supports_5ghz = have_a;
1833 
1834 	return (ic->ic_nchans == 0 ? ENXIO : 0);
1835 }
1836 
1837 static uint32_t
1838 bwn_shm_read_4(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1839 {
1840 	uint32_t ret;
1841 
1842 	BWN_ASSERT_LOCKED(mac->mac_sc);
1843 
1844 	if (way == BWN_SHARED) {
1845 		KASSERT((offset & 0x0001) == 0,
1846 		    ("%s:%d warn", __func__, __LINE__));
1847 		if (offset & 0x0003) {
1848 			bwn_shm_ctlword(mac, way, offset >> 2);
1849 			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1850 			ret <<= 16;
1851 			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1852 			ret |= BWN_READ_2(mac, BWN_SHM_DATA);
1853 			goto out;
1854 		}
1855 		offset >>= 2;
1856 	}
1857 	bwn_shm_ctlword(mac, way, offset);
1858 	ret = BWN_READ_4(mac, BWN_SHM_DATA);
1859 out:
1860 	return (ret);
1861 }
1862 
1863 static uint16_t
1864 bwn_shm_read_2(struct bwn_mac *mac, uint16_t way, uint16_t offset)
1865 {
1866 	uint16_t ret;
1867 
1868 	BWN_ASSERT_LOCKED(mac->mac_sc);
1869 
1870 	if (way == BWN_SHARED) {
1871 		KASSERT((offset & 0x0001) == 0,
1872 		    ("%s:%d warn", __func__, __LINE__));
1873 		if (offset & 0x0003) {
1874 			bwn_shm_ctlword(mac, way, offset >> 2);
1875 			ret = BWN_READ_2(mac, BWN_SHM_DATA_UNALIGNED);
1876 			goto out;
1877 		}
1878 		offset >>= 2;
1879 	}
1880 	bwn_shm_ctlword(mac, way, offset);
1881 	ret = BWN_READ_2(mac, BWN_SHM_DATA);
1882 out:
1883 
1884 	return (ret);
1885 }
1886 
1887 static void
1888 bwn_shm_ctlword(struct bwn_mac *mac, uint16_t way,
1889     uint16_t offset)
1890 {
1891 	uint32_t control;
1892 
1893 	control = way;
1894 	control <<= 16;
1895 	control |= offset;
1896 	BWN_WRITE_4(mac, BWN_SHM_CONTROL, control);
1897 }
1898 
1899 static void
1900 bwn_shm_write_4(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1901     uint32_t value)
1902 {
1903 	BWN_ASSERT_LOCKED(mac->mac_sc);
1904 
1905 	if (way == BWN_SHARED) {
1906 		KASSERT((offset & 0x0001) == 0,
1907 		    ("%s:%d warn", __func__, __LINE__));
1908 		if (offset & 0x0003) {
1909 			bwn_shm_ctlword(mac, way, offset >> 2);
1910 			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED,
1911 				    (value >> 16) & 0xffff);
1912 			bwn_shm_ctlword(mac, way, (offset >> 2) + 1);
1913 			BWN_WRITE_2(mac, BWN_SHM_DATA, value & 0xffff);
1914 			return;
1915 		}
1916 		offset >>= 2;
1917 	}
1918 	bwn_shm_ctlword(mac, way, offset);
1919 	BWN_WRITE_4(mac, BWN_SHM_DATA, value);
1920 }
1921 
1922 static void
1923 bwn_shm_write_2(struct bwn_mac *mac, uint16_t way, uint16_t offset,
1924     uint16_t value)
1925 {
1926 	BWN_ASSERT_LOCKED(mac->mac_sc);
1927 
1928 	if (way == BWN_SHARED) {
1929 		KASSERT((offset & 0x0001) == 0,
1930 		    ("%s:%d warn", __func__, __LINE__));
1931 		if (offset & 0x0003) {
1932 			bwn_shm_ctlword(mac, way, offset >> 2);
1933 			BWN_WRITE_2(mac, BWN_SHM_DATA_UNALIGNED, value);
1934 			return;
1935 		}
1936 		offset >>= 2;
1937 	}
1938 	bwn_shm_ctlword(mac, way, offset);
1939 	BWN_WRITE_2(mac, BWN_SHM_DATA, value);
1940 }
1941 
1942 static void
1943 bwn_addchan(struct ieee80211_channel *c, int freq, int flags, int ieee,
1944     int txpow)
1945 {
1946 
1947 	c->ic_freq = freq;
1948 	c->ic_flags = flags;
1949 	c->ic_ieee = ieee;
1950 	c->ic_minpower = 0;
1951 	c->ic_maxpower = 2 * txpow;
1952 	c->ic_maxregpower = txpow;
1953 }
1954 
1955 static void
1956 bwn_addchannels(struct ieee80211_channel chans[], int maxchans, int *nchans,
1957     const struct bwn_channelinfo *ci, int flags)
1958 {
1959 	struct ieee80211_channel *c;
1960 	int i;
1961 
1962 	c = &chans[*nchans];
1963 
1964 	for (i = 0; i < ci->nchannels; i++) {
1965 		const struct bwn_channel *hc;
1966 
1967 		hc = &ci->channels[i];
1968 		if (*nchans >= maxchans)
1969 			break;
1970 		bwn_addchan(c, hc->freq, flags, hc->ieee, hc->maxTxPow);
1971 		c++, (*nchans)++;
1972 		if (flags == IEEE80211_CHAN_G || flags == IEEE80211_CHAN_HTG) {
1973 			/* g channel have a separate b-only entry */
1974 			if (*nchans >= maxchans)
1975 				break;
1976 			c[0] = c[-1];
1977 			c[-1].ic_flags = IEEE80211_CHAN_B;
1978 			c++, (*nchans)++;
1979 		}
1980 		if (flags == IEEE80211_CHAN_HTG) {
1981 			/* HT g channel have a separate g-only entry */
1982 			if (*nchans >= maxchans)
1983 				break;
1984 			c[-1].ic_flags = IEEE80211_CHAN_G;
1985 			c[0] = c[-1];
1986 			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
1987 			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
1988 			c++, (*nchans)++;
1989 		}
1990 		if (flags == IEEE80211_CHAN_HTA) {
1991 			/* HT a channel have a separate a-only entry */
1992 			if (*nchans >= maxchans)
1993 				break;
1994 			c[-1].ic_flags = IEEE80211_CHAN_A;
1995 			c[0] = c[-1];
1996 			c[0].ic_flags &= ~IEEE80211_CHAN_HT;
1997 			c[0].ic_flags |= IEEE80211_CHAN_HT20;	/* HT20 */
1998 			c++, (*nchans)++;
1999 		}
2000 	}
2001 }
2002 
2003 static int
2004 bwn_phy_g_attach(struct bwn_mac *mac)
2005 {
2006 	struct bwn_softc *sc = mac->mac_sc;
2007 	struct bwn_phy *phy = &mac->mac_phy;
2008 	struct bwn_phy_g *pg = &phy->phy_g;
2009 	unsigned int i;
2010 	int16_t pab0, pab1, pab2;
2011 	static int8_t bwn_phy_g_tssi2dbm_table[] = BWN_PHY_G_TSSI2DBM_TABLE;
2012 	int8_t bg;
2013 
2014 	bg = (int8_t)siba_sprom_get_tssi_bg(sc->sc_dev);
2015 	pab0 = (int16_t)siba_sprom_get_pa0b0(sc->sc_dev);
2016 	pab1 = (int16_t)siba_sprom_get_pa0b1(sc->sc_dev);
2017 	pab2 = (int16_t)siba_sprom_get_pa0b2(sc->sc_dev);
2018 
2019 	if ((siba_get_chipid(sc->sc_dev) == 0x4301) && (phy->rf_ver != 0x2050))
2020 		device_printf(sc->sc_dev, "not supported anymore\n");
2021 
2022 	pg->pg_flags = 0;
2023 	if (pab0 == 0 || pab1 == 0 || pab2 == 0 || pab0 == -1 || pab1 == -1 ||
2024 	    pab2 == -1) {
2025 		pg->pg_idletssi = 52;
2026 		pg->pg_tssi2dbm = bwn_phy_g_tssi2dbm_table;
2027 		return (0);
2028 	}
2029 
2030 	pg->pg_idletssi = (bg == 0 || bg == -1) ? 62 : bg;
2031 	pg->pg_tssi2dbm = (uint8_t *)malloc(64, M_DEVBUF, M_NOWAIT | M_ZERO);
2032 	if (pg->pg_tssi2dbm == NULL) {
2033 		device_printf(sc->sc_dev, "failed to allocate buffer\n");
2034 		return (ENOMEM);
2035 	}
2036 	for (i = 0; i < 64; i++) {
2037 		int32_t m1, m2, f, q, delta;
2038 		int8_t j = 0;
2039 
2040 		m1 = BWN_TSSI2DBM(16 * pab0 + i * pab1, 32);
2041 		m2 = MAX(BWN_TSSI2DBM(32768 + i * pab2, 256), 1);
2042 		f = 256;
2043 
2044 		do {
2045 			if (j > 15) {
2046 				device_printf(sc->sc_dev,
2047 				    "failed to generate tssi2dBm\n");
2048 				free(pg->pg_tssi2dbm, M_DEVBUF);
2049 				return (ENOMEM);
2050 			}
2051 			q = BWN_TSSI2DBM(f * 4096 - BWN_TSSI2DBM(m2 * f, 16) *
2052 			    f, 2048);
2053 			delta = abs(q - f);
2054 			f = q;
2055 			j++;
2056 		} while (delta >= 2);
2057 
2058 		pg->pg_tssi2dbm[i] = MIN(MAX(BWN_TSSI2DBM(m1 * f, 8192), -127),
2059 		    128);
2060 	}
2061 
2062 	pg->pg_flags |= BWN_PHY_G_FLAG_TSSITABLE_ALLOC;
2063 	return (0);
2064 }
2065 
2066 static void
2067 bwn_phy_g_detach(struct bwn_mac *mac)
2068 {
2069 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
2070 
2071 	if (pg->pg_flags & BWN_PHY_G_FLAG_TSSITABLE_ALLOC) {
2072 		free(pg->pg_tssi2dbm, M_DEVBUF);
2073 		pg->pg_tssi2dbm = NULL;
2074 	}
2075 	pg->pg_flags = 0;
2076 }
2077 
2078 static void
2079 bwn_phy_g_init_pre(struct bwn_mac *mac)
2080 {
2081 	struct bwn_phy *phy = &mac->mac_phy;
2082 	struct bwn_phy_g *pg = &phy->phy_g;
2083 	void *tssi2dbm;
2084 	int idletssi;
2085 	unsigned int i;
2086 
2087 	tssi2dbm = pg->pg_tssi2dbm;
2088 	idletssi = pg->pg_idletssi;
2089 
2090 	memset(pg, 0, sizeof(*pg));
2091 
2092 	pg->pg_tssi2dbm = tssi2dbm;
2093 	pg->pg_idletssi = idletssi;
2094 
2095 	memset(pg->pg_minlowsig, 0xff, sizeof(pg->pg_minlowsig));
2096 
2097 	for (i = 0; i < N(pg->pg_nrssi); i++)
2098 		pg->pg_nrssi[i] = -1000;
2099 	for (i = 0; i < N(pg->pg_nrssi_lt); i++)
2100 		pg->pg_nrssi_lt[i] = i;
2101 	pg->pg_lofcal = 0xffff;
2102 	pg->pg_initval = 0xffff;
2103 	pg->pg_immode = BWN_IMMODE_NONE;
2104 	pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_UNKNOWN;
2105 	pg->pg_avgtssi = 0xff;
2106 
2107 	pg->pg_loctl.tx_bias = 0xff;
2108 	TAILQ_INIT(&pg->pg_loctl.calib_list);
2109 }
2110 
2111 static int
2112 bwn_phy_g_prepare_hw(struct bwn_mac *mac)
2113 {
2114 	struct bwn_phy *phy = &mac->mac_phy;
2115 	struct bwn_phy_g *pg = &phy->phy_g;
2116 	struct bwn_softc *sc = mac->mac_sc;
2117 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2118 	static const struct bwn_rfatt rfatt0[] = {
2119 		{ 3, 0 }, { 1, 0 }, { 5, 0 }, { 7, 0 },	{ 9, 0 }, { 2, 0 },
2120 		{ 0, 0 }, { 4, 0 }, { 6, 0 }, { 8, 0 }, { 1, 1 }, { 2, 1 },
2121 		{ 3, 1 }, { 4, 1 }
2122 	};
2123 	static const struct bwn_rfatt rfatt1[] = {
2124 		{ 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 1 }, { 12, 1 },
2125 		{ 14, 1 }
2126 	};
2127 	static const struct bwn_rfatt rfatt2[] = {
2128 		{ 0, 1 }, { 2, 1 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 9, 1 },
2129 		{ 9, 1 }
2130 	};
2131 	static const struct bwn_bbatt bbatt_0[] = {
2132 		{ 0 }, { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, { 6 }, { 7 }, { 8 }
2133 	};
2134 
2135 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
2136 
2137 	if (phy->rf_ver == 0x2050 && phy->rf_rev < 6)
2138 		pg->pg_bbatt.att = 0;
2139 	else
2140 		pg->pg_bbatt.att = 2;
2141 
2142 	/* prepare Radio Attenuation */
2143 	pg->pg_rfatt.padmix = 0;
2144 
2145 	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
2146 	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BCM4309G) {
2147 		if (siba_get_pci_revid(sc->sc_dev) < 0x43) {
2148 			pg->pg_rfatt.att = 2;
2149 			goto done;
2150 		} else if (siba_get_pci_revid(sc->sc_dev) < 0x51) {
2151 			pg->pg_rfatt.att = 3;
2152 			goto done;
2153 		}
2154 	}
2155 
2156 	if (phy->type == BWN_PHYTYPE_A) {
2157 		pg->pg_rfatt.att = 0x60;
2158 		goto done;
2159 	}
2160 
2161 	switch (phy->rf_ver) {
2162 	case 0x2050:
2163 		switch (phy->rf_rev) {
2164 		case 0:
2165 			pg->pg_rfatt.att = 5;
2166 			goto done;
2167 		case 1:
2168 			if (phy->type == BWN_PHYTYPE_G) {
2169 				if (siba_get_pci_subvendor(sc->sc_dev) ==
2170 				    SIBA_BOARDVENDOR_BCM &&
2171 				    siba_get_pci_subdevice(sc->sc_dev) ==
2172 				    SIBA_BOARD_BCM4309G &&
2173 				    siba_get_pci_revid(sc->sc_dev) >= 30)
2174 					pg->pg_rfatt.att = 3;
2175 				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2176 				    SIBA_BOARDVENDOR_BCM &&
2177 				    siba_get_pci_subdevice(sc->sc_dev) ==
2178 				    SIBA_BOARD_BU4306)
2179 					pg->pg_rfatt.att = 3;
2180 				else
2181 					pg->pg_rfatt.att = 1;
2182 			} else {
2183 				if (siba_get_pci_subvendor(sc->sc_dev) ==
2184 				    SIBA_BOARDVENDOR_BCM &&
2185 				    siba_get_pci_subdevice(sc->sc_dev) ==
2186 				    SIBA_BOARD_BCM4309G &&
2187 				    siba_get_pci_revid(sc->sc_dev) >= 30)
2188 					pg->pg_rfatt.att = 7;
2189 				else
2190 					pg->pg_rfatt.att = 6;
2191 			}
2192 			goto done;
2193 		case 2:
2194 			if (phy->type == BWN_PHYTYPE_G) {
2195 				if (siba_get_pci_subvendor(sc->sc_dev) ==
2196 				    SIBA_BOARDVENDOR_BCM &&
2197 				    siba_get_pci_subdevice(sc->sc_dev) ==
2198 				    SIBA_BOARD_BCM4309G &&
2199 				    siba_get_pci_revid(sc->sc_dev) >= 30)
2200 					pg->pg_rfatt.att = 3;
2201 				else if (siba_get_pci_subvendor(sc->sc_dev) ==
2202 				    SIBA_BOARDVENDOR_BCM &&
2203 				    siba_get_pci_subdevice(sc->sc_dev) ==
2204 				    SIBA_BOARD_BU4306)
2205 					pg->pg_rfatt.att = 5;
2206 				else if (siba_get_chipid(sc->sc_dev) == 0x4320)
2207 					pg->pg_rfatt.att = 4;
2208 				else
2209 					pg->pg_rfatt.att = 3;
2210 			} else
2211 				pg->pg_rfatt.att = 6;
2212 			goto done;
2213 		case 3:
2214 			pg->pg_rfatt.att = 5;
2215 			goto done;
2216 		case 4:
2217 		case 5:
2218 			pg->pg_rfatt.att = 1;
2219 			goto done;
2220 		case 6:
2221 		case 7:
2222 			pg->pg_rfatt.att = 5;
2223 			goto done;
2224 		case 8:
2225 			pg->pg_rfatt.att = 0xa;
2226 			pg->pg_rfatt.padmix = 1;
2227 			goto done;
2228 		case 9:
2229 		default:
2230 			pg->pg_rfatt.att = 5;
2231 			goto done;
2232 		}
2233 		break;
2234 	case 0x2053:
2235 		switch (phy->rf_rev) {
2236 		case 1:
2237 			pg->pg_rfatt.att = 6;
2238 			goto done;
2239 		}
2240 		break;
2241 	}
2242 	pg->pg_rfatt.att = 5;
2243 done:
2244 	pg->pg_txctl = (bwn_phy_g_txctl(mac) << 4);
2245 
2246 	if (!bwn_has_hwpctl(mac)) {
2247 		lo->rfatt.array = rfatt0;
2248 		lo->rfatt.len = N(rfatt0);
2249 		lo->rfatt.min = 0;
2250 		lo->rfatt.max = 9;
2251 		goto genbbatt;
2252 	}
2253 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
2254 		lo->rfatt.array = rfatt1;
2255 		lo->rfatt.len = N(rfatt1);
2256 		lo->rfatt.min = 0;
2257 		lo->rfatt.max = 14;
2258 		goto genbbatt;
2259 	}
2260 	lo->rfatt.array = rfatt2;
2261 	lo->rfatt.len = N(rfatt2);
2262 	lo->rfatt.min = 0;
2263 	lo->rfatt.max = 9;
2264 genbbatt:
2265 	lo->bbatt.array = bbatt_0;
2266 	lo->bbatt.len = N(bbatt_0);
2267 	lo->bbatt.min = 0;
2268 	lo->bbatt.max = 8;
2269 
2270 	BWN_READ_4(mac, BWN_MACCTL);
2271 	if (phy->rev == 1) {
2272 		phy->gmode = 0;
2273 		bwn_reset_core(mac, 0);
2274 		bwn_phy_g_init_sub(mac);
2275 		phy->gmode = 1;
2276 		bwn_reset_core(mac, BWN_TGSLOW_SUPPORT_G);
2277 	}
2278 	return (0);
2279 }
2280 
2281 static uint16_t
2282 bwn_phy_g_txctl(struct bwn_mac *mac)
2283 {
2284 	struct bwn_phy *phy = &mac->mac_phy;
2285 
2286 	if (phy->rf_ver != 0x2050)
2287 		return (0);
2288 	if (phy->rf_rev == 1)
2289 		return (BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX);
2290 	if (phy->rf_rev < 6)
2291 		return (BWN_TXCTL_PA2DB);
2292 	if (phy->rf_rev == 8)
2293 		return (BWN_TXCTL_TXMIX);
2294 	return (0);
2295 }
2296 
2297 static int
2298 bwn_phy_g_init(struct bwn_mac *mac)
2299 {
2300 
2301 	bwn_phy_g_init_sub(mac);
2302 	return (0);
2303 }
2304 
2305 static void
2306 bwn_phy_g_exit(struct bwn_mac *mac)
2307 {
2308 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
2309 	struct bwn_lo_calib *cal, *tmp;
2310 
2311 	if (lo == NULL)
2312 		return;
2313 	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2314 		TAILQ_REMOVE(&lo->calib_list, cal, list);
2315 		free(cal, M_DEVBUF);
2316 	}
2317 }
2318 
2319 static uint16_t
2320 bwn_phy_g_read(struct bwn_mac *mac, uint16_t reg)
2321 {
2322 
2323 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2324 	return (BWN_READ_2(mac, BWN_PHYDATA));
2325 }
2326 
2327 static void
2328 bwn_phy_g_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2329 {
2330 
2331 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
2332 	BWN_WRITE_2(mac, BWN_PHYDATA, value);
2333 }
2334 
2335 static uint16_t
2336 bwn_phy_g_rf_read(struct bwn_mac *mac, uint16_t reg)
2337 {
2338 
2339 	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2340 	BWN_WRITE_2(mac, BWN_RFCTL, reg | 0x80);
2341 	return (BWN_READ_2(mac, BWN_RFDATALO));
2342 }
2343 
2344 static void
2345 bwn_phy_g_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
2346 {
2347 
2348 	KASSERT(reg != 1, ("%s:%d: fail", __func__, __LINE__));
2349 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
2350 	BWN_WRITE_2(mac, BWN_RFDATALO, value);
2351 }
2352 
2353 static int
2354 bwn_phy_g_hwpctl(struct bwn_mac *mac)
2355 {
2356 
2357 	return (mac->mac_phy.rev >= 6);
2358 }
2359 
2360 static void
2361 bwn_phy_g_rf_onoff(struct bwn_mac *mac, int on)
2362 {
2363 	struct bwn_phy *phy = &mac->mac_phy;
2364 	struct bwn_phy_g *pg = &phy->phy_g;
2365 	unsigned int channel;
2366 	uint16_t rfover, rfoverval;
2367 
2368 	if (on) {
2369 		if (phy->rf_on)
2370 			return;
2371 
2372 		BWN_PHY_WRITE(mac, 0x15, 0x8000);
2373 		BWN_PHY_WRITE(mac, 0x15, 0xcc00);
2374 		BWN_PHY_WRITE(mac, 0x15, (phy->gmode ? 0xc0 : 0x0));
2375 		if (pg->pg_flags & BWN_PHY_G_FLAG_RADIOCTX_VALID) {
2376 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
2377 			    pg->pg_radioctx_over);
2378 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
2379 			    pg->pg_radioctx_overval);
2380 			pg->pg_flags &= ~BWN_PHY_G_FLAG_RADIOCTX_VALID;
2381 		}
2382 		channel = phy->chan;
2383 		bwn_phy_g_switch_chan(mac, 6, 1);
2384 		bwn_phy_g_switch_chan(mac, channel, 0);
2385 		return;
2386 	}
2387 
2388 	rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
2389 	rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
2390 	pg->pg_radioctx_over = rfover;
2391 	pg->pg_radioctx_overval = rfoverval;
2392 	pg->pg_flags |= BWN_PHY_G_FLAG_RADIOCTX_VALID;
2393 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover | 0x008c);
2394 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval & 0xff73);
2395 }
2396 
2397 static int
2398 bwn_phy_g_switch_channel(struct bwn_mac *mac, uint32_t newchan)
2399 {
2400 
2401 	if ((newchan < 1) || (newchan > 14))
2402 		return (EINVAL);
2403 	bwn_phy_g_switch_chan(mac, newchan, 0);
2404 
2405 	return (0);
2406 }
2407 
2408 static uint32_t
2409 bwn_phy_g_get_default_chan(struct bwn_mac *mac)
2410 {
2411 
2412 	return (1);
2413 }
2414 
2415 static void
2416 bwn_phy_g_set_antenna(struct bwn_mac *mac, int antenna)
2417 {
2418 	struct bwn_phy *phy = &mac->mac_phy;
2419 	uint64_t hf;
2420 	int autodiv = 0;
2421 	uint16_t tmp;
2422 
2423 	if (antenna == BWN_ANTAUTO0 || antenna == BWN_ANTAUTO1)
2424 		autodiv = 1;
2425 
2426 	hf = bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER;
2427 	bwn_hf_write(mac, hf);
2428 
2429 	BWN_PHY_WRITE(mac, BWN_PHY_BBANDCFG,
2430 	    (BWN_PHY_READ(mac, BWN_PHY_BBANDCFG) & ~BWN_PHY_BBANDCFG_RXANT) |
2431 	    ((autodiv ? BWN_ANTAUTO1 : antenna)
2432 		<< BWN_PHY_BBANDCFG_RXANT_SHIFT));
2433 
2434 	if (autodiv) {
2435 		tmp = BWN_PHY_READ(mac, BWN_PHY_ANTDWELL);
2436 		if (antenna == BWN_ANTAUTO1)
2437 			tmp &= ~BWN_PHY_ANTDWELL_AUTODIV1;
2438 		else
2439 			tmp |= BWN_PHY_ANTDWELL_AUTODIV1;
2440 		BWN_PHY_WRITE(mac, BWN_PHY_ANTDWELL, tmp);
2441 	}
2442 	tmp = BWN_PHY_READ(mac, BWN_PHY_ANTWRSETT);
2443 	if (autodiv)
2444 		tmp |= BWN_PHY_ANTWRSETT_ARXDIV;
2445 	else
2446 		tmp &= ~BWN_PHY_ANTWRSETT_ARXDIV;
2447 	BWN_PHY_WRITE(mac, BWN_PHY_ANTWRSETT, tmp);
2448 	if (phy->rev >= 2) {
2449 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM61,
2450 		    BWN_PHY_READ(mac, BWN_PHY_OFDM61) | BWN_PHY_OFDM61_10);
2451 		BWN_PHY_WRITE(mac, BWN_PHY_DIVSRCHGAINBACK,
2452 		    (BWN_PHY_READ(mac, BWN_PHY_DIVSRCHGAINBACK) & 0xff00) |
2453 		    0x15);
2454 		if (phy->rev == 2)
2455 			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED, 8);
2456 		else
2457 			BWN_PHY_WRITE(mac, BWN_PHY_ADIVRELATED,
2458 			    (BWN_PHY_READ(mac, BWN_PHY_ADIVRELATED) & 0xff00) |
2459 			    8);
2460 	}
2461 	if (phy->rev >= 6)
2462 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM9B, 0xdc);
2463 
2464 	hf |= BWN_HF_UCODE_ANTDIV_HELPER;
2465 	bwn_hf_write(mac, hf);
2466 }
2467 
2468 static int
2469 bwn_phy_g_im(struct bwn_mac *mac, int mode)
2470 {
2471 	struct bwn_phy *phy = &mac->mac_phy;
2472 	struct bwn_phy_g *pg = &phy->phy_g;
2473 
2474 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2475 	KASSERT(mode == BWN_IMMODE_NONE, ("%s: fail", __func__));
2476 
2477 	if (phy->rev == 0 || !phy->gmode)
2478 		return (ENODEV);
2479 
2480 	pg->pg_aci_wlan_automatic = 0;
2481 	return (0);
2482 }
2483 
2484 static int
2485 bwn_phy_g_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi)
2486 {
2487 	struct bwn_phy *phy = &mac->mac_phy;
2488 	struct bwn_phy_g *pg = &phy->phy_g;
2489 	struct bwn_softc *sc = mac->mac_sc;
2490 	unsigned int tssi;
2491 	int cck, ofdm;
2492 	int power;
2493 	int rfatt, bbatt;
2494 	unsigned int max;
2495 
2496 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
2497 
2498 	cck = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_CCK);
2499 	ofdm = bwn_phy_shm_tssi_read(mac, BWN_SHARED_TSSI_OFDM_G);
2500 	if (cck < 0 && ofdm < 0) {
2501 		if (ignore_tssi == 0)
2502 			return (BWN_TXPWR_RES_DONE);
2503 		cck = 0;
2504 		ofdm = 0;
2505 	}
2506 	tssi = (cck < 0) ? ofdm : ((ofdm < 0) ? cck : (cck + ofdm) / 2);
2507 	if (pg->pg_avgtssi != 0xff)
2508 		tssi = (tssi + pg->pg_avgtssi) / 2;
2509 	pg->pg_avgtssi = tssi;
2510 	KASSERT(tssi < BWN_TSSI_MAX, ("%s:%d: fail", __func__, __LINE__));
2511 
2512 	max = siba_sprom_get_maxpwr_bg(sc->sc_dev);
2513 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
2514 		max -= 3;
2515 	if (max >= 120) {
2516 		device_printf(sc->sc_dev, "invalid max TX-power value\n");
2517 		max = 80;
2518 		siba_sprom_set_maxpwr_bg(sc->sc_dev, max);
2519 	}
2520 
2521 	power = MIN(MAX((phy->txpower < 0) ? 0 : (phy->txpower << 2), 0), max) -
2522 	    (pg->pg_tssi2dbm[MIN(MAX(pg->pg_idletssi - pg->pg_curtssi +
2523 	     tssi, 0x00), 0x3f)]);
2524 	if (power == 0)
2525 		return (BWN_TXPWR_RES_DONE);
2526 
2527 	rfatt = -((power + 7) / 8);
2528 	bbatt = (-(power / 2)) - (4 * rfatt);
2529 	if ((rfatt == 0) && (bbatt == 0))
2530 		return (BWN_TXPWR_RES_DONE);
2531 	pg->pg_bbatt_delta = bbatt;
2532 	pg->pg_rfatt_delta = rfatt;
2533 	return (BWN_TXPWR_RES_NEED_ADJUST);
2534 }
2535 
2536 static void
2537 bwn_phy_g_set_txpwr(struct bwn_mac *mac)
2538 {
2539 	struct bwn_phy *phy = &mac->mac_phy;
2540 	struct bwn_phy_g *pg = &phy->phy_g;
2541 	struct bwn_softc *sc = mac->mac_sc;
2542 	int rfatt, bbatt;
2543 	uint8_t txctl;
2544 
2545 	bwn_mac_suspend(mac);
2546 
2547 	BWN_ASSERT_LOCKED(sc);
2548 
2549 	bbatt = pg->pg_bbatt.att;
2550 	bbatt += pg->pg_bbatt_delta;
2551 	rfatt = pg->pg_rfatt.att;
2552 	rfatt += pg->pg_rfatt_delta;
2553 
2554 	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2555 	txctl = pg->pg_txctl;
2556 	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 2)) {
2557 		if (rfatt <= 1) {
2558 			if (txctl == 0) {
2559 				txctl = BWN_TXCTL_PA2DB | BWN_TXCTL_TXMIX;
2560 				rfatt += 2;
2561 				bbatt += 2;
2562 			} else if (siba_sprom_get_bf_lo(sc->sc_dev) &
2563 			    BWN_BFL_PACTRL) {
2564 				bbatt += 4 * (rfatt - 2);
2565 				rfatt = 2;
2566 			}
2567 		} else if (rfatt > 4 && txctl) {
2568 			txctl = 0;
2569 			if (bbatt < 3) {
2570 				rfatt -= 3;
2571 				bbatt += 2;
2572 			} else {
2573 				rfatt -= 2;
2574 				bbatt -= 2;
2575 			}
2576 		}
2577 	}
2578 	pg->pg_txctl = txctl;
2579 	bwn_phy_g_setatt(mac, &bbatt, &rfatt);
2580 	pg->pg_rfatt.att = rfatt;
2581 	pg->pg_bbatt.att = bbatt;
2582 
2583 	DPRINTF(sc, BWN_DEBUG_TXPOW, "%s: adjust TX power\n", __func__);
2584 
2585 	bwn_phy_lock(mac);
2586 	bwn_rf_lock(mac);
2587 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
2588 	    pg->pg_txctl);
2589 	bwn_rf_unlock(mac);
2590 	bwn_phy_unlock(mac);
2591 
2592 	bwn_mac_enable(mac);
2593 }
2594 
2595 static void
2596 bwn_phy_g_task_15s(struct bwn_mac *mac)
2597 {
2598 	struct bwn_phy *phy = &mac->mac_phy;
2599 	struct bwn_phy_g *pg = &phy->phy_g;
2600 	struct bwn_softc *sc = mac->mac_sc;
2601 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
2602 	unsigned long expire, now;
2603 	struct bwn_lo_calib *cal, *tmp;
2604 	uint8_t expired = 0;
2605 
2606 	bwn_mac_suspend(mac);
2607 
2608 	if (lo == NULL)
2609 		goto fail;
2610 
2611 	BWN_GETTIME(now);
2612 	if (bwn_has_hwpctl(mac)) {
2613 		expire = now - BWN_LO_PWRVEC_EXPIRE;
2614 		if (time_before(lo->pwr_vec_read_time, expire)) {
2615 			bwn_lo_get_powervector(mac);
2616 			bwn_phy_g_dc_lookup_init(mac, 0);
2617 		}
2618 		goto fail;
2619 	}
2620 
2621 	expire = now - BWN_LO_CALIB_EXPIRE;
2622 	TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
2623 		if (!time_before(cal->calib_time, expire))
2624 			continue;
2625 		if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
2626 		    BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
2627 			KASSERT(!expired, ("%s:%d: fail", __func__, __LINE__));
2628 			expired = 1;
2629 		}
2630 
2631 		DPRINTF(sc, BWN_DEBUG_LO, "expired BB %u RF %u %u I %d Q %d\n",
2632 		    cal->bbatt.att, cal->rfatt.att, cal->rfatt.padmix,
2633 		    cal->ctl.i, cal->ctl.q);
2634 
2635 		TAILQ_REMOVE(&lo->calib_list, cal, list);
2636 		free(cal, M_DEVBUF);
2637 	}
2638 	if (expired || TAILQ_EMPTY(&lo->calib_list)) {
2639 		cal = bwn_lo_calibset(mac, &pg->pg_bbatt,
2640 		    &pg->pg_rfatt);
2641 		if (cal == NULL) {
2642 			device_printf(sc->sc_dev,
2643 			    "failed to recalibrate LO\n");
2644 			goto fail;
2645 		}
2646 		TAILQ_INSERT_TAIL(&lo->calib_list, cal, list);
2647 		bwn_lo_write(mac, &cal->ctl);
2648 	}
2649 
2650 fail:
2651 	bwn_mac_enable(mac);
2652 }
2653 
2654 static void
2655 bwn_phy_g_task_60s(struct bwn_mac *mac)
2656 {
2657 	struct bwn_phy *phy = &mac->mac_phy;
2658 	struct bwn_softc *sc = mac->mac_sc;
2659 	uint8_t old = phy->chan;
2660 
2661 	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI))
2662 		return;
2663 
2664 	bwn_mac_suspend(mac);
2665 	bwn_nrssi_slope_11g(mac);
2666 	if ((phy->rf_ver == 0x2050) && (phy->rf_rev == 8)) {
2667 		bwn_switch_channel(mac, (old >= 8) ? 1 : 13);
2668 		bwn_switch_channel(mac, old);
2669 	}
2670 	bwn_mac_enable(mac);
2671 }
2672 
2673 static void
2674 bwn_phy_switch_analog(struct bwn_mac *mac, int on)
2675 {
2676 
2677 	BWN_WRITE_2(mac, BWN_PHY0, on ? 0 : 0xf4);
2678 }
2679 
2680 static int
2681 bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
2682 	const struct ieee80211_bpf_params *params)
2683 {
2684 	struct ieee80211com *ic = ni->ni_ic;
2685 	struct bwn_softc *sc = ic->ic_softc;
2686 	struct bwn_mac *mac = sc->sc_curmac;
2687 	int error;
2688 
2689 	if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0 ||
2690 	    mac->mac_status < BWN_MAC_STATUS_STARTED) {
2691 		m_freem(m);
2692 		return (ENETDOWN);
2693 	}
2694 
2695 	BWN_LOCK(sc);
2696 	if (bwn_tx_isfull(sc, m)) {
2697 		m_freem(m);
2698 		BWN_UNLOCK(sc);
2699 		return (ENOBUFS);
2700 	}
2701 
2702 	error = bwn_tx_start(sc, ni, m);
2703 	if (error == 0)
2704 		sc->sc_watchdog_timer = 5;
2705 	BWN_UNLOCK(sc);
2706 	return (error);
2707 }
2708 
2709 /*
2710  * Callback from the 802.11 layer to update the slot time
2711  * based on the current setting.  We use it to notify the
2712  * firmware of ERP changes and the f/w takes care of things
2713  * like slot time and preamble.
2714  */
2715 static void
2716 bwn_updateslot(struct ieee80211com *ic)
2717 {
2718 	struct bwn_softc *sc = ic->ic_softc;
2719 	struct bwn_mac *mac;
2720 
2721 	BWN_LOCK(sc);
2722 	if (sc->sc_flags & BWN_FLAG_RUNNING) {
2723 		mac = (struct bwn_mac *)sc->sc_curmac;
2724 		bwn_set_slot_time(mac, IEEE80211_GET_SLOTTIME(ic));
2725 	}
2726 	BWN_UNLOCK(sc);
2727 }
2728 
2729 /*
2730  * Callback from the 802.11 layer after a promiscuous mode change.
2731  * Note this interface does not check the operating mode as this
2732  * is an internal callback and we are expected to honor the current
2733  * state (e.g. this is used for setting the interface in promiscuous
2734  * mode when operating in hostap mode to do ACS).
2735  */
2736 static void
2737 bwn_update_promisc(struct ieee80211com *ic)
2738 {
2739 	struct bwn_softc *sc = ic->ic_softc;
2740 	struct bwn_mac *mac = sc->sc_curmac;
2741 
2742 	BWN_LOCK(sc);
2743 	mac = sc->sc_curmac;
2744 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2745 		if (ic->ic_promisc > 0)
2746 			sc->sc_filters |= BWN_MACCTL_PROMISC;
2747 		else
2748 			sc->sc_filters &= ~BWN_MACCTL_PROMISC;
2749 		bwn_set_opmode(mac);
2750 	}
2751 	BWN_UNLOCK(sc);
2752 }
2753 
2754 /*
2755  * Callback from the 802.11 layer to update WME parameters.
2756  */
2757 static int
2758 bwn_wme_update(struct ieee80211com *ic)
2759 {
2760 	struct bwn_softc *sc = ic->ic_softc;
2761 	struct bwn_mac *mac = sc->sc_curmac;
2762 	struct wmeParams *wmep;
2763 	int i;
2764 
2765 	BWN_LOCK(sc);
2766 	mac = sc->sc_curmac;
2767 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2768 		bwn_mac_suspend(mac);
2769 		for (i = 0; i < N(sc->sc_wmeParams); i++) {
2770 			wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[i];
2771 			bwn_wme_loadparams(mac, wmep, bwn_wme_shm_offsets[i]);
2772 		}
2773 		bwn_mac_enable(mac);
2774 	}
2775 	BWN_UNLOCK(sc);
2776 	return (0);
2777 }
2778 
2779 static void
2780 bwn_scan_start(struct ieee80211com *ic)
2781 {
2782 	struct bwn_softc *sc = ic->ic_softc;
2783 	struct bwn_mac *mac;
2784 
2785 	BWN_LOCK(sc);
2786 	mac = sc->sc_curmac;
2787 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2788 		sc->sc_filters |= BWN_MACCTL_BEACON_PROMISC;
2789 		bwn_set_opmode(mac);
2790 		/* disable CFP update during scan */
2791 		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_SKIP_CFP_UPDATE);
2792 	}
2793 	BWN_UNLOCK(sc);
2794 }
2795 
2796 static void
2797 bwn_scan_end(struct ieee80211com *ic)
2798 {
2799 	struct bwn_softc *sc = ic->ic_softc;
2800 	struct bwn_mac *mac;
2801 
2802 	BWN_LOCK(sc);
2803 	mac = sc->sc_curmac;
2804 	if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
2805 		sc->sc_filters &= ~BWN_MACCTL_BEACON_PROMISC;
2806 		bwn_set_opmode(mac);
2807 		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_SKIP_CFP_UPDATE);
2808 	}
2809 	BWN_UNLOCK(sc);
2810 }
2811 
2812 static void
2813 bwn_set_channel(struct ieee80211com *ic)
2814 {
2815 	struct bwn_softc *sc = ic->ic_softc;
2816 	struct bwn_mac *mac = sc->sc_curmac;
2817 	struct bwn_phy *phy = &mac->mac_phy;
2818 	int chan, error;
2819 
2820 	BWN_LOCK(sc);
2821 
2822 	error = bwn_switch_band(sc, ic->ic_curchan);
2823 	if (error)
2824 		goto fail;
2825 	bwn_mac_suspend(mac);
2826 	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
2827 	chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
2828 	if (chan != phy->chan)
2829 		bwn_switch_channel(mac, chan);
2830 
2831 	/* TX power level */
2832 	if (ic->ic_curchan->ic_maxpower != 0 &&
2833 	    ic->ic_curchan->ic_maxpower != phy->txpower) {
2834 		phy->txpower = ic->ic_curchan->ic_maxpower / 2;
2835 		bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME |
2836 		    BWN_TXPWR_IGNORE_TSSI);
2837 	}
2838 
2839 	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
2840 	if (phy->set_antenna)
2841 		phy->set_antenna(mac, BWN_ANT_DEFAULT);
2842 
2843 	if (sc->sc_rf_enabled != phy->rf_on) {
2844 		if (sc->sc_rf_enabled) {
2845 			bwn_rf_turnon(mac);
2846 			if (!(mac->mac_flags & BWN_MAC_FLAG_RADIO_ON))
2847 				device_printf(sc->sc_dev,
2848 				    "please turn on the RF switch\n");
2849 		} else
2850 			bwn_rf_turnoff(mac);
2851 	}
2852 
2853 	bwn_mac_enable(mac);
2854 
2855 fail:
2856 	/*
2857 	 * Setup radio tap channel freq and flags
2858 	 */
2859 	sc->sc_tx_th.wt_chan_freq = sc->sc_rx_th.wr_chan_freq =
2860 		htole16(ic->ic_curchan->ic_freq);
2861 	sc->sc_tx_th.wt_chan_flags = sc->sc_rx_th.wr_chan_flags =
2862 		htole16(ic->ic_curchan->ic_flags & 0xffff);
2863 
2864 	BWN_UNLOCK(sc);
2865 }
2866 
2867 static struct ieee80211vap *
2868 bwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
2869     enum ieee80211_opmode opmode, int flags,
2870     const uint8_t bssid[IEEE80211_ADDR_LEN],
2871     const uint8_t mac[IEEE80211_ADDR_LEN])
2872 {
2873 	struct ieee80211vap *vap;
2874 	struct bwn_vap *bvp;
2875 
2876 	switch (opmode) {
2877 	case IEEE80211_M_HOSTAP:
2878 	case IEEE80211_M_MBSS:
2879 	case IEEE80211_M_STA:
2880 	case IEEE80211_M_WDS:
2881 	case IEEE80211_M_MONITOR:
2882 	case IEEE80211_M_IBSS:
2883 	case IEEE80211_M_AHDEMO:
2884 		break;
2885 	default:
2886 		return (NULL);
2887 	}
2888 
2889 	bvp = malloc(sizeof(struct bwn_vap), M_80211_VAP, M_WAITOK | M_ZERO);
2890 	vap = &bvp->bv_vap;
2891 	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
2892 	/* override with driver methods */
2893 	bvp->bv_newstate = vap->iv_newstate;
2894 	vap->iv_newstate = bwn_newstate;
2895 
2896 	/* override max aid so sta's cannot assoc when we're out of sta id's */
2897 	vap->iv_max_aid = BWN_STAID_MAX;
2898 
2899 	ieee80211_ratectl_init(vap);
2900 
2901 	/* complete setup */
2902 	ieee80211_vap_attach(vap, ieee80211_media_change,
2903 	    ieee80211_media_status, mac);
2904 	return (vap);
2905 }
2906 
2907 static void
2908 bwn_vap_delete(struct ieee80211vap *vap)
2909 {
2910 	struct bwn_vap *bvp = BWN_VAP(vap);
2911 
2912 	ieee80211_ratectl_deinit(vap);
2913 	ieee80211_vap_detach(vap);
2914 	free(bvp, M_80211_VAP);
2915 }
2916 
2917 static int
2918 bwn_init(struct bwn_softc *sc)
2919 {
2920 	struct bwn_mac *mac;
2921 	int error;
2922 
2923 	BWN_ASSERT_LOCKED(sc);
2924 
2925 	bzero(sc->sc_bssid, IEEE80211_ADDR_LEN);
2926 	sc->sc_flags |= BWN_FLAG_NEED_BEACON_TP;
2927 	sc->sc_filters = 0;
2928 	bwn_wme_clear(sc);
2929 	sc->sc_beacons[0] = sc->sc_beacons[1] = 0;
2930 	sc->sc_rf_enabled = 1;
2931 
2932 	mac = sc->sc_curmac;
2933 	if (mac->mac_status == BWN_MAC_STATUS_UNINIT) {
2934 		error = bwn_core_init(mac);
2935 		if (error != 0)
2936 			return (error);
2937 	}
2938 	if (mac->mac_status == BWN_MAC_STATUS_INITED)
2939 		bwn_core_start(mac);
2940 
2941 	bwn_set_opmode(mac);
2942 	bwn_set_pretbtt(mac);
2943 	bwn_spu_setdelay(mac, 0);
2944 	bwn_set_macaddr(mac);
2945 
2946 	sc->sc_flags |= BWN_FLAG_RUNNING;
2947 	callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
2948 	callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
2949 
2950 	return (0);
2951 }
2952 
2953 static void
2954 bwn_stop(struct bwn_softc *sc)
2955 {
2956 	struct bwn_mac *mac = sc->sc_curmac;
2957 
2958 	BWN_ASSERT_LOCKED(sc);
2959 
2960 	if (mac->mac_status >= BWN_MAC_STATUS_INITED) {
2961 		/* XXX FIXME opmode not based on VAP */
2962 		bwn_set_opmode(mac);
2963 		bwn_set_macaddr(mac);
2964 	}
2965 
2966 	if (mac->mac_status >= BWN_MAC_STATUS_STARTED)
2967 		bwn_core_stop(mac);
2968 
2969 	callout_stop(&sc->sc_led_blink_ch);
2970 	sc->sc_led_blinking = 0;
2971 
2972 	bwn_core_exit(mac);
2973 	sc->sc_rf_enabled = 0;
2974 
2975 	sc->sc_flags &= ~BWN_FLAG_RUNNING;
2976 }
2977 
2978 static void
2979 bwn_wme_clear(struct bwn_softc *sc)
2980 {
2981 #define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
2982 	struct wmeParams *p;
2983 	unsigned int i;
2984 
2985 	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
2986 	    ("%s:%d: fail", __func__, __LINE__));
2987 
2988 	for (i = 0; i < N(sc->sc_wmeParams); i++) {
2989 		p = &(sc->sc_wmeParams[i]);
2990 
2991 		switch (bwn_wme_shm_offsets[i]) {
2992 		case BWN_WME_VOICE:
2993 			p->wmep_txopLimit = 0;
2994 			p->wmep_aifsn = 2;
2995 			/* XXX FIXME: log2(cwmin) */
2996 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
2997 			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
2998 			break;
2999 		case BWN_WME_VIDEO:
3000 			p->wmep_txopLimit = 0;
3001 			p->wmep_aifsn = 2;
3002 			/* XXX FIXME: log2(cwmin) */
3003 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3004 			p->wmep_logcwmax = MS(0x0001, WME_PARAM_LOGCWMAX);
3005 			break;
3006 		case BWN_WME_BESTEFFORT:
3007 			p->wmep_txopLimit = 0;
3008 			p->wmep_aifsn = 3;
3009 			/* XXX FIXME: log2(cwmin) */
3010 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3011 			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3012 			break;
3013 		case BWN_WME_BACKGROUND:
3014 			p->wmep_txopLimit = 0;
3015 			p->wmep_aifsn = 7;
3016 			/* XXX FIXME: log2(cwmin) */
3017 			p->wmep_logcwmin = MS(0x0001, WME_PARAM_LOGCWMIN);
3018 			p->wmep_logcwmax = MS(0x03ff, WME_PARAM_LOGCWMAX);
3019 			break;
3020 		default:
3021 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3022 		}
3023 	}
3024 }
3025 
3026 static int
3027 bwn_core_init(struct bwn_mac *mac)
3028 {
3029 	struct bwn_softc *sc = mac->mac_sc;
3030 	uint64_t hf;
3031 	int error;
3032 
3033 	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3034 	    ("%s:%d: fail", __func__, __LINE__));
3035 
3036 	siba_powerup(sc->sc_dev, 0);
3037 	if (!siba_dev_isup(sc->sc_dev))
3038 		bwn_reset_core(mac,
3039 		    mac->mac_phy.gmode ? BWN_TGSLOW_SUPPORT_G : 0);
3040 
3041 	mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
3042 	mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
3043 	mac->mac_phy.hwpctl = (bwn_hwpctl) ? 1 : 0;
3044 	BWN_GETTIME(mac->mac_phy.nexttime);
3045 	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
3046 	bzero(&mac->mac_stats, sizeof(mac->mac_stats));
3047 	mac->mac_stats.link_noise = -95;
3048 	mac->mac_reason_intr = 0;
3049 	bzero(mac->mac_reason, sizeof(mac->mac_reason));
3050 	mac->mac_intr_mask = BWN_INTR_MASKTEMPLATE;
3051 #ifdef BWN_DEBUG
3052 	if (sc->sc_debug & BWN_DEBUG_XMIT)
3053 		mac->mac_intr_mask &= ~BWN_INTR_PHY_TXERR;
3054 #endif
3055 	mac->mac_suspended = 1;
3056 	mac->mac_task_state = 0;
3057 	memset(&mac->mac_noise, 0, sizeof(mac->mac_noise));
3058 
3059 	mac->mac_phy.init_pre(mac);
3060 
3061 	siba_pcicore_intr(sc->sc_dev);
3062 
3063 	siba_fix_imcfglobug(sc->sc_dev);
3064 	bwn_bt_disable(mac);
3065 	if (mac->mac_phy.prepare_hw) {
3066 		error = mac->mac_phy.prepare_hw(mac);
3067 		if (error)
3068 			goto fail0;
3069 	}
3070 	error = bwn_chip_init(mac);
3071 	if (error)
3072 		goto fail0;
3073 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_COREREV,
3074 	    siba_get_revid(sc->sc_dev));
3075 	hf = bwn_hf_read(mac);
3076 	if (mac->mac_phy.type == BWN_PHYTYPE_G) {
3077 		hf |= BWN_HF_GPHY_SYM_WORKAROUND;
3078 		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
3079 			hf |= BWN_HF_PAGAINBOOST_OFDM_ON;
3080 		if (mac->mac_phy.rev == 1)
3081 			hf |= BWN_HF_GPHY_DC_CANCELFILTER;
3082 	}
3083 	if (mac->mac_phy.rf_ver == 0x2050) {
3084 		if (mac->mac_phy.rf_rev < 6)
3085 			hf |= BWN_HF_FORCE_VCO_RECALC;
3086 		if (mac->mac_phy.rf_rev == 6)
3087 			hf |= BWN_HF_4318_TSSI;
3088 	}
3089 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW)
3090 		hf |= BWN_HF_SLOWCLOCK_REQ_OFF;
3091 	if ((siba_get_type(sc->sc_dev) == SIBA_TYPE_PCI) &&
3092 	    (siba_get_pcicore_revid(sc->sc_dev) <= 10))
3093 		hf |= BWN_HF_PCI_SLOWCLOCK_WORKAROUND;
3094 	hf &= ~BWN_HF_SKIP_CFP_UPDATE;
3095 	bwn_hf_write(mac, hf);
3096 
3097 	bwn_set_txretry(mac, BWN_RETRY_SHORT, BWN_RETRY_LONG);
3098 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SHORT_RETRY_FALLBACK, 3);
3099 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_LONG_RETRY_FALLBACK, 2);
3100 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_MAXTIME, 1);
3101 
3102 	bwn_rate_init(mac);
3103 	bwn_set_phytxctl(mac);
3104 
3105 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MIN,
3106 	    (mac->mac_phy.type == BWN_PHYTYPE_B) ? 0x1f : 0xf);
3107 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_CONT_MAX, 0x3ff);
3108 
3109 	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
3110 		bwn_pio_init(mac);
3111 	else
3112 		bwn_dma_init(mac);
3113 	bwn_wme_init(mac);
3114 	bwn_spu_setdelay(mac, 1);
3115 	bwn_bt_enable(mac);
3116 
3117 	siba_powerup(sc->sc_dev,
3118 	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_CRYSTAL_NOSLOW));
3119 	bwn_set_macaddr(mac);
3120 	bwn_crypt_init(mac);
3121 
3122 	/* XXX LED initializatin */
3123 
3124 	mac->mac_status = BWN_MAC_STATUS_INITED;
3125 
3126 	return (error);
3127 
3128 fail0:
3129 	siba_powerdown(sc->sc_dev);
3130 	KASSERT(mac->mac_status == BWN_MAC_STATUS_UNINIT,
3131 	    ("%s:%d: fail", __func__, __LINE__));
3132 	return (error);
3133 }
3134 
3135 static void
3136 bwn_core_start(struct bwn_mac *mac)
3137 {
3138 	struct bwn_softc *sc = mac->mac_sc;
3139 	uint32_t tmp;
3140 
3141 	KASSERT(mac->mac_status == BWN_MAC_STATUS_INITED,
3142 	    ("%s:%d: fail", __func__, __LINE__));
3143 
3144 	if (siba_get_revid(sc->sc_dev) < 5)
3145 		return;
3146 
3147 	while (1) {
3148 		tmp = BWN_READ_4(mac, BWN_XMITSTAT_0);
3149 		if (!(tmp & 0x00000001))
3150 			break;
3151 		tmp = BWN_READ_4(mac, BWN_XMITSTAT_1);
3152 	}
3153 
3154 	bwn_mac_enable(mac);
3155 	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
3156 	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
3157 
3158 	mac->mac_status = BWN_MAC_STATUS_STARTED;
3159 }
3160 
3161 static void
3162 bwn_core_exit(struct bwn_mac *mac)
3163 {
3164 	struct bwn_softc *sc = mac->mac_sc;
3165 	uint32_t macctl;
3166 
3167 	BWN_ASSERT_LOCKED(mac->mac_sc);
3168 
3169 	KASSERT(mac->mac_status <= BWN_MAC_STATUS_INITED,
3170 	    ("%s:%d: fail", __func__, __LINE__));
3171 
3172 	if (mac->mac_status != BWN_MAC_STATUS_INITED)
3173 		return;
3174 	mac->mac_status = BWN_MAC_STATUS_UNINIT;
3175 
3176 	macctl = BWN_READ_4(mac, BWN_MACCTL);
3177 	macctl &= ~BWN_MACCTL_MCODE_RUN;
3178 	macctl |= BWN_MACCTL_MCODE_JMP0;
3179 	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3180 
3181 	bwn_dma_stop(mac);
3182 	bwn_pio_stop(mac);
3183 	bwn_chip_exit(mac);
3184 	mac->mac_phy.switch_analog(mac, 0);
3185 	siba_dev_down(sc->sc_dev, 0);
3186 	siba_powerdown(sc->sc_dev);
3187 }
3188 
3189 static void
3190 bwn_bt_disable(struct bwn_mac *mac)
3191 {
3192 	struct bwn_softc *sc = mac->mac_sc;
3193 
3194 	(void)sc;
3195 	/* XXX do nothing yet */
3196 }
3197 
3198 static int
3199 bwn_chip_init(struct bwn_mac *mac)
3200 {
3201 	struct bwn_softc *sc = mac->mac_sc;
3202 	struct bwn_phy *phy = &mac->mac_phy;
3203 	uint32_t macctl;
3204 	int error;
3205 
3206 	macctl = BWN_MACCTL_IHR_ON | BWN_MACCTL_SHM_ON | BWN_MACCTL_STA;
3207 	if (phy->gmode)
3208 		macctl |= BWN_MACCTL_GMODE;
3209 	BWN_WRITE_4(mac, BWN_MACCTL, macctl);
3210 
3211 	error = bwn_fw_fillinfo(mac);
3212 	if (error)
3213 		return (error);
3214 	error = bwn_fw_loaducode(mac);
3215 	if (error)
3216 		return (error);
3217 
3218 	error = bwn_gpio_init(mac);
3219 	if (error)
3220 		return (error);
3221 
3222 	error = bwn_fw_loadinitvals(mac);
3223 	if (error) {
3224 		siba_gpio_set(sc->sc_dev, 0);
3225 		return (error);
3226 	}
3227 	phy->switch_analog(mac, 1);
3228 	error = bwn_phy_init(mac);
3229 	if (error) {
3230 		siba_gpio_set(sc->sc_dev, 0);
3231 		return (error);
3232 	}
3233 	if (phy->set_im)
3234 		phy->set_im(mac, BWN_IMMODE_NONE);
3235 	if (phy->set_antenna)
3236 		phy->set_antenna(mac, BWN_ANT_DEFAULT);
3237 	bwn_set_txantenna(mac, BWN_ANT_DEFAULT);
3238 
3239 	if (phy->type == BWN_PHYTYPE_B)
3240 		BWN_WRITE_2(mac, 0x005e, BWN_READ_2(mac, 0x005e) | 0x0004);
3241 	BWN_WRITE_4(mac, 0x0100, 0x01000000);
3242 	if (siba_get_revid(sc->sc_dev) < 5)
3243 		BWN_WRITE_4(mac, 0x010c, 0x01000000);
3244 
3245 	BWN_WRITE_4(mac, BWN_MACCTL,
3246 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_STA);
3247 	BWN_WRITE_4(mac, BWN_MACCTL,
3248 	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_STA);
3249 	bwn_shm_write_2(mac, BWN_SHARED, 0x0074, 0x0000);
3250 
3251 	bwn_set_opmode(mac);
3252 	if (siba_get_revid(sc->sc_dev) < 3) {
3253 		BWN_WRITE_2(mac, 0x060e, 0x0000);
3254 		BWN_WRITE_2(mac, 0x0610, 0x8000);
3255 		BWN_WRITE_2(mac, 0x0604, 0x0000);
3256 		BWN_WRITE_2(mac, 0x0606, 0x0200);
3257 	} else {
3258 		BWN_WRITE_4(mac, 0x0188, 0x80000000);
3259 		BWN_WRITE_4(mac, 0x018c, 0x02000000);
3260 	}
3261 	BWN_WRITE_4(mac, BWN_INTR_REASON, 0x00004000);
3262 	BWN_WRITE_4(mac, BWN_DMA0_INTR_MASK, 0x0001dc00);
3263 	BWN_WRITE_4(mac, BWN_DMA1_INTR_MASK, 0x0000dc00);
3264 	BWN_WRITE_4(mac, BWN_DMA2_INTR_MASK, 0x0000dc00);
3265 	BWN_WRITE_4(mac, BWN_DMA3_INTR_MASK, 0x0001dc00);
3266 	BWN_WRITE_4(mac, BWN_DMA4_INTR_MASK, 0x0000dc00);
3267 	BWN_WRITE_4(mac, BWN_DMA5_INTR_MASK, 0x0000dc00);
3268 	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
3269 	    siba_read_4(sc->sc_dev, SIBA_TGSLOW) | 0x00100000);
3270 	BWN_WRITE_2(mac, BWN_POWERUP_DELAY, siba_get_cc_powerdelay(sc->sc_dev));
3271 	return (error);
3272 }
3273 
3274 /* read hostflags */
3275 static uint64_t
3276 bwn_hf_read(struct bwn_mac *mac)
3277 {
3278 	uint64_t ret;
3279 
3280 	ret = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFHI);
3281 	ret <<= 16;
3282 	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFMI);
3283 	ret <<= 16;
3284 	ret |= bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO);
3285 	return (ret);
3286 }
3287 
3288 static void
3289 bwn_hf_write(struct bwn_mac *mac, uint64_t value)
3290 {
3291 
3292 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFLO,
3293 	    (value & 0x00000000ffffull));
3294 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFMI,
3295 	    (value & 0x0000ffff0000ull) >> 16);
3296 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_HFHI,
3297 	    (value & 0xffff00000000ULL) >> 32);
3298 }
3299 
3300 static void
3301 bwn_set_txretry(struct bwn_mac *mac, int s, int l)
3302 {
3303 
3304 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_SHORT_RETRY, MIN(s, 0xf));
3305 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_SCRATCH_LONG_RETRY, MIN(l, 0xf));
3306 }
3307 
3308 static void
3309 bwn_rate_init(struct bwn_mac *mac)
3310 {
3311 
3312 	switch (mac->mac_phy.type) {
3313 	case BWN_PHYTYPE_A:
3314 	case BWN_PHYTYPE_G:
3315 	case BWN_PHYTYPE_LP:
3316 	case BWN_PHYTYPE_N:
3317 		bwn_rate_write(mac, BWN_OFDM_RATE_6MB, 1);
3318 		bwn_rate_write(mac, BWN_OFDM_RATE_12MB, 1);
3319 		bwn_rate_write(mac, BWN_OFDM_RATE_18MB, 1);
3320 		bwn_rate_write(mac, BWN_OFDM_RATE_24MB, 1);
3321 		bwn_rate_write(mac, BWN_OFDM_RATE_36MB, 1);
3322 		bwn_rate_write(mac, BWN_OFDM_RATE_48MB, 1);
3323 		bwn_rate_write(mac, BWN_OFDM_RATE_54MB, 1);
3324 		if (mac->mac_phy.type == BWN_PHYTYPE_A)
3325 			break;
3326 		/* FALLTHROUGH */
3327 	case BWN_PHYTYPE_B:
3328 		bwn_rate_write(mac, BWN_CCK_RATE_1MB, 0);
3329 		bwn_rate_write(mac, BWN_CCK_RATE_2MB, 0);
3330 		bwn_rate_write(mac, BWN_CCK_RATE_5MB, 0);
3331 		bwn_rate_write(mac, BWN_CCK_RATE_11MB, 0);
3332 		break;
3333 	default:
3334 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3335 	}
3336 }
3337 
3338 static void
3339 bwn_rate_write(struct bwn_mac *mac, uint16_t rate, int ofdm)
3340 {
3341 	uint16_t offset;
3342 
3343 	if (ofdm) {
3344 		offset = 0x480;
3345 		offset += (bwn_plcp_getofdm(rate) & 0x000f) * 2;
3346 	} else {
3347 		offset = 0x4c0;
3348 		offset += (bwn_plcp_getcck(rate) & 0x000f) * 2;
3349 	}
3350 	bwn_shm_write_2(mac, BWN_SHARED, offset + 0x20,
3351 	    bwn_shm_read_2(mac, BWN_SHARED, offset));
3352 }
3353 
3354 static uint8_t
3355 bwn_plcp_getcck(const uint8_t bitrate)
3356 {
3357 
3358 	switch (bitrate) {
3359 	case BWN_CCK_RATE_1MB:
3360 		return (0x0a);
3361 	case BWN_CCK_RATE_2MB:
3362 		return (0x14);
3363 	case BWN_CCK_RATE_5MB:
3364 		return (0x37);
3365 	case BWN_CCK_RATE_11MB:
3366 		return (0x6e);
3367 	}
3368 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3369 	return (0);
3370 }
3371 
3372 static uint8_t
3373 bwn_plcp_getofdm(const uint8_t bitrate)
3374 {
3375 
3376 	switch (bitrate) {
3377 	case BWN_OFDM_RATE_6MB:
3378 		return (0xb);
3379 	case BWN_OFDM_RATE_9MB:
3380 		return (0xf);
3381 	case BWN_OFDM_RATE_12MB:
3382 		return (0xa);
3383 	case BWN_OFDM_RATE_18MB:
3384 		return (0xe);
3385 	case BWN_OFDM_RATE_24MB:
3386 		return (0x9);
3387 	case BWN_OFDM_RATE_36MB:
3388 		return (0xd);
3389 	case BWN_OFDM_RATE_48MB:
3390 		return (0x8);
3391 	case BWN_OFDM_RATE_54MB:
3392 		return (0xc);
3393 	}
3394 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3395 	return (0);
3396 }
3397 
3398 static void
3399 bwn_set_phytxctl(struct bwn_mac *mac)
3400 {
3401 	uint16_t ctl;
3402 
3403 	ctl = (BWN_TX_PHY_ENC_CCK | BWN_TX_PHY_ANT01AUTO |
3404 	    BWN_TX_PHY_TXPWR);
3405 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_BEACON_PHYCTL, ctl);
3406 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, ctl);
3407 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, ctl);
3408 }
3409 
3410 static void
3411 bwn_pio_init(struct bwn_mac *mac)
3412 {
3413 	struct bwn_pio *pio = &mac->mac_method.pio;
3414 
3415 	BWN_WRITE_4(mac, BWN_MACCTL, BWN_READ_4(mac, BWN_MACCTL)
3416 	    & ~BWN_MACCTL_BIGENDIAN);
3417 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RX_PADOFFSET, 0);
3418 
3419 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BK], 0);
3420 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_BE], 1);
3421 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VI], 2);
3422 	bwn_pio_set_txqueue(mac, &pio->wme[WME_AC_VO], 3);
3423 	bwn_pio_set_txqueue(mac, &pio->mcast, 4);
3424 	bwn_pio_setupqueue_rx(mac, &pio->rx, 0);
3425 }
3426 
3427 static void
3428 bwn_pio_set_txqueue(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3429     int index)
3430 {
3431 	struct bwn_pio_txpkt *tp;
3432 	struct bwn_softc *sc = mac->mac_sc;
3433 	unsigned int i;
3434 
3435 	tq->tq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_TXQOFFSET(mac);
3436 	tq->tq_index = index;
3437 
3438 	tq->tq_free = BWN_PIO_MAX_TXPACKETS;
3439 	if (siba_get_revid(sc->sc_dev) >= 8)
3440 		tq->tq_size = 1920;
3441 	else {
3442 		tq->tq_size = bwn_pio_read_2(mac, tq, BWN_PIO_TXQBUFSIZE);
3443 		tq->tq_size -= 80;
3444 	}
3445 
3446 	TAILQ_INIT(&tq->tq_pktlist);
3447 	for (i = 0; i < N(tq->tq_pkts); i++) {
3448 		tp = &(tq->tq_pkts[i]);
3449 		tp->tp_index = i;
3450 		tp->tp_queue = tq;
3451 		TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
3452 	}
3453 }
3454 
3455 static uint16_t
3456 bwn_pio_idx2base(struct bwn_mac *mac, int index)
3457 {
3458 	struct bwn_softc *sc = mac->mac_sc;
3459 	static const uint16_t bases[] = {
3460 		BWN_PIO_BASE0,
3461 		BWN_PIO_BASE1,
3462 		BWN_PIO_BASE2,
3463 		BWN_PIO_BASE3,
3464 		BWN_PIO_BASE4,
3465 		BWN_PIO_BASE5,
3466 		BWN_PIO_BASE6,
3467 		BWN_PIO_BASE7,
3468 	};
3469 	static const uint16_t bases_rev11[] = {
3470 		BWN_PIO11_BASE0,
3471 		BWN_PIO11_BASE1,
3472 		BWN_PIO11_BASE2,
3473 		BWN_PIO11_BASE3,
3474 		BWN_PIO11_BASE4,
3475 		BWN_PIO11_BASE5,
3476 	};
3477 
3478 	if (siba_get_revid(sc->sc_dev) >= 11) {
3479 		if (index >= N(bases_rev11))
3480 			device_printf(sc->sc_dev, "%s: warning\n", __func__);
3481 		return (bases_rev11[index]);
3482 	}
3483 	if (index >= N(bases))
3484 		device_printf(sc->sc_dev, "%s: warning\n", __func__);
3485 	return (bases[index]);
3486 }
3487 
3488 static void
3489 bwn_pio_setupqueue_rx(struct bwn_mac *mac, struct bwn_pio_rxqueue *prq,
3490     int index)
3491 {
3492 	struct bwn_softc *sc = mac->mac_sc;
3493 
3494 	prq->prq_mac = mac;
3495 	prq->prq_rev = siba_get_revid(sc->sc_dev);
3496 	prq->prq_base = bwn_pio_idx2base(mac, index) + BWN_PIO_RXQOFFSET(mac);
3497 	bwn_dma_rxdirectfifo(mac, index, 1);
3498 }
3499 
3500 static void
3501 bwn_destroy_pioqueue_tx(struct bwn_pio_txqueue *tq)
3502 {
3503 	if (tq == NULL)
3504 		return;
3505 	bwn_pio_cancel_tx_packets(tq);
3506 }
3507 
3508 static void
3509 bwn_destroy_queue_tx(struct bwn_pio_txqueue *pio)
3510 {
3511 
3512 	bwn_destroy_pioqueue_tx(pio);
3513 }
3514 
3515 static uint16_t
3516 bwn_pio_read_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
3517     uint16_t offset)
3518 {
3519 
3520 	return (BWN_READ_2(mac, tq->tq_base + offset));
3521 }
3522 
3523 static void
3524 bwn_dma_rxdirectfifo(struct bwn_mac *mac, int idx, uint8_t enable)
3525 {
3526 	uint32_t ctl;
3527 	int type;
3528 	uint16_t base;
3529 
3530 	type = bwn_dma_mask2type(bwn_dma_mask(mac));
3531 	base = bwn_dma_base(type, idx);
3532 	if (type == BWN_DMA_64BIT) {
3533 		ctl = BWN_READ_4(mac, base + BWN_DMA64_RXCTL);
3534 		ctl &= ~BWN_DMA64_RXDIRECTFIFO;
3535 		if (enable)
3536 			ctl |= BWN_DMA64_RXDIRECTFIFO;
3537 		BWN_WRITE_4(mac, base + BWN_DMA64_RXCTL, ctl);
3538 	} else {
3539 		ctl = BWN_READ_4(mac, base + BWN_DMA32_RXCTL);
3540 		ctl &= ~BWN_DMA32_RXDIRECTFIFO;
3541 		if (enable)
3542 			ctl |= BWN_DMA32_RXDIRECTFIFO;
3543 		BWN_WRITE_4(mac, base + BWN_DMA32_RXCTL, ctl);
3544 	}
3545 }
3546 
3547 static uint64_t
3548 bwn_dma_mask(struct bwn_mac *mac)
3549 {
3550 	uint32_t tmp;
3551 	uint16_t base;
3552 
3553 	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
3554 	if (tmp & SIBA_TGSHIGH_DMA64)
3555 		return (BWN_DMA_BIT_MASK(64));
3556 	base = bwn_dma_base(0, 0);
3557 	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
3558 	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
3559 	if (tmp & BWN_DMA32_TXADDREXT_MASK)
3560 		return (BWN_DMA_BIT_MASK(32));
3561 
3562 	return (BWN_DMA_BIT_MASK(30));
3563 }
3564 
3565 static int
3566 bwn_dma_mask2type(uint64_t dmamask)
3567 {
3568 
3569 	if (dmamask == BWN_DMA_BIT_MASK(30))
3570 		return (BWN_DMA_30BIT);
3571 	if (dmamask == BWN_DMA_BIT_MASK(32))
3572 		return (BWN_DMA_32BIT);
3573 	if (dmamask == BWN_DMA_BIT_MASK(64))
3574 		return (BWN_DMA_64BIT);
3575 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3576 	return (BWN_DMA_30BIT);
3577 }
3578 
3579 static void
3580 bwn_pio_cancel_tx_packets(struct bwn_pio_txqueue *tq)
3581 {
3582 	struct bwn_pio_txpkt *tp;
3583 	unsigned int i;
3584 
3585 	for (i = 0; i < N(tq->tq_pkts); i++) {
3586 		tp = &(tq->tq_pkts[i]);
3587 		if (tp->tp_m) {
3588 			m_freem(tp->tp_m);
3589 			tp->tp_m = NULL;
3590 		}
3591 	}
3592 }
3593 
3594 static uint16_t
3595 bwn_dma_base(int type, int controller_idx)
3596 {
3597 	static const uint16_t map64[] = {
3598 		BWN_DMA64_BASE0,
3599 		BWN_DMA64_BASE1,
3600 		BWN_DMA64_BASE2,
3601 		BWN_DMA64_BASE3,
3602 		BWN_DMA64_BASE4,
3603 		BWN_DMA64_BASE5,
3604 	};
3605 	static const uint16_t map32[] = {
3606 		BWN_DMA32_BASE0,
3607 		BWN_DMA32_BASE1,
3608 		BWN_DMA32_BASE2,
3609 		BWN_DMA32_BASE3,
3610 		BWN_DMA32_BASE4,
3611 		BWN_DMA32_BASE5,
3612 	};
3613 
3614 	if (type == BWN_DMA_64BIT) {
3615 		KASSERT(controller_idx >= 0 && controller_idx < N(map64),
3616 		    ("%s:%d: fail", __func__, __LINE__));
3617 		return (map64[controller_idx]);
3618 	}
3619 	KASSERT(controller_idx >= 0 && controller_idx < N(map32),
3620 	    ("%s:%d: fail", __func__, __LINE__));
3621 	return (map32[controller_idx]);
3622 }
3623 
3624 static void
3625 bwn_dma_init(struct bwn_mac *mac)
3626 {
3627 	struct bwn_dma *dma = &mac->mac_method.dma;
3628 
3629 	/* setup TX DMA channels. */
3630 	bwn_dma_setup(dma->wme[WME_AC_BK]);
3631 	bwn_dma_setup(dma->wme[WME_AC_BE]);
3632 	bwn_dma_setup(dma->wme[WME_AC_VI]);
3633 	bwn_dma_setup(dma->wme[WME_AC_VO]);
3634 	bwn_dma_setup(dma->mcast);
3635 	/* setup RX DMA channel. */
3636 	bwn_dma_setup(dma->rx);
3637 }
3638 
3639 static struct bwn_dma_ring *
3640 bwn_dma_ringsetup(struct bwn_mac *mac, int controller_index,
3641     int for_tx, int type)
3642 {
3643 	struct bwn_dma *dma = &mac->mac_method.dma;
3644 	struct bwn_dma_ring *dr;
3645 	struct bwn_dmadesc_generic *desc;
3646 	struct bwn_dmadesc_meta *mt;
3647 	struct bwn_softc *sc = mac->mac_sc;
3648 	int error, i;
3649 
3650 	dr = malloc(sizeof(*dr), M_DEVBUF, M_NOWAIT | M_ZERO);
3651 	if (dr == NULL)
3652 		goto out;
3653 	dr->dr_numslots = BWN_RXRING_SLOTS;
3654 	if (for_tx)
3655 		dr->dr_numslots = BWN_TXRING_SLOTS;
3656 
3657 	dr->dr_meta = malloc(dr->dr_numslots * sizeof(struct bwn_dmadesc_meta),
3658 	    M_DEVBUF, M_NOWAIT | M_ZERO);
3659 	if (dr->dr_meta == NULL)
3660 		goto fail0;
3661 
3662 	dr->dr_type = type;
3663 	dr->dr_mac = mac;
3664 	dr->dr_base = bwn_dma_base(type, controller_index);
3665 	dr->dr_index = controller_index;
3666 	if (type == BWN_DMA_64BIT) {
3667 		dr->getdesc = bwn_dma_64_getdesc;
3668 		dr->setdesc = bwn_dma_64_setdesc;
3669 		dr->start_transfer = bwn_dma_64_start_transfer;
3670 		dr->suspend = bwn_dma_64_suspend;
3671 		dr->resume = bwn_dma_64_resume;
3672 		dr->get_curslot = bwn_dma_64_get_curslot;
3673 		dr->set_curslot = bwn_dma_64_set_curslot;
3674 	} else {
3675 		dr->getdesc = bwn_dma_32_getdesc;
3676 		dr->setdesc = bwn_dma_32_setdesc;
3677 		dr->start_transfer = bwn_dma_32_start_transfer;
3678 		dr->suspend = bwn_dma_32_suspend;
3679 		dr->resume = bwn_dma_32_resume;
3680 		dr->get_curslot = bwn_dma_32_get_curslot;
3681 		dr->set_curslot = bwn_dma_32_set_curslot;
3682 	}
3683 	if (for_tx) {
3684 		dr->dr_tx = 1;
3685 		dr->dr_curslot = -1;
3686 	} else {
3687 		if (dr->dr_index == 0) {
3688 			dr->dr_rx_bufsize = BWN_DMA0_RX_BUFFERSIZE;
3689 			dr->dr_frameoffset = BWN_DMA0_RX_FRAMEOFFSET;
3690 		} else
3691 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
3692 	}
3693 
3694 	error = bwn_dma_allocringmemory(dr);
3695 	if (error)
3696 		goto fail2;
3697 
3698 	if (for_tx) {
3699 		/*
3700 		 * Assumption: BWN_TXRING_SLOTS can be divided by
3701 		 * BWN_TX_SLOTS_PER_FRAME
3702 		 */
3703 		KASSERT(BWN_TXRING_SLOTS % BWN_TX_SLOTS_PER_FRAME == 0,
3704 		    ("%s:%d: fail", __func__, __LINE__));
3705 
3706 		dr->dr_txhdr_cache =
3707 		    malloc((dr->dr_numslots / BWN_TX_SLOTS_PER_FRAME) *
3708 			BWN_HDRSIZE(mac), M_DEVBUF, M_NOWAIT | M_ZERO);
3709 		KASSERT(dr->dr_txhdr_cache != NULL,
3710 		    ("%s:%d: fail", __func__, __LINE__));
3711 
3712 		/*
3713 		 * Create TX ring DMA stuffs
3714 		 */
3715 		error = bus_dma_tag_create(dma->parent_dtag,
3716 				    BWN_ALIGN, 0,
3717 				    BUS_SPACE_MAXADDR,
3718 				    BUS_SPACE_MAXADDR,
3719 				    NULL, NULL,
3720 				    BWN_HDRSIZE(mac),
3721 				    1,
3722 				    BUS_SPACE_MAXSIZE_32BIT,
3723 				    0,
3724 				    NULL, NULL,
3725 				    &dr->dr_txring_dtag);
3726 		if (error) {
3727 			device_printf(sc->sc_dev,
3728 			    "can't create TX ring DMA tag: TODO frees\n");
3729 			goto fail1;
3730 		}
3731 
3732 		for (i = 0; i < dr->dr_numslots; i += 2) {
3733 			dr->getdesc(dr, i, &desc, &mt);
3734 
3735 			mt->mt_txtype = BWN_DMADESC_METATYPE_HEADER;
3736 			mt->mt_m = NULL;
3737 			mt->mt_ni = NULL;
3738 			mt->mt_islast = 0;
3739 			error = bus_dmamap_create(dr->dr_txring_dtag, 0,
3740 			    &mt->mt_dmap);
3741 			if (error) {
3742 				device_printf(sc->sc_dev,
3743 				     "can't create RX buf DMA map\n");
3744 				goto fail1;
3745 			}
3746 
3747 			dr->getdesc(dr, i + 1, &desc, &mt);
3748 
3749 			mt->mt_txtype = BWN_DMADESC_METATYPE_BODY;
3750 			mt->mt_m = NULL;
3751 			mt->mt_ni = NULL;
3752 			mt->mt_islast = 1;
3753 			error = bus_dmamap_create(dma->txbuf_dtag, 0,
3754 			    &mt->mt_dmap);
3755 			if (error) {
3756 				device_printf(sc->sc_dev,
3757 				     "can't create RX buf DMA map\n");
3758 				goto fail1;
3759 			}
3760 		}
3761 	} else {
3762 		error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3763 		    &dr->dr_spare_dmap);
3764 		if (error) {
3765 			device_printf(sc->sc_dev,
3766 			    "can't create RX buf DMA map\n");
3767 			goto out;		/* XXX wrong! */
3768 		}
3769 
3770 		for (i = 0; i < dr->dr_numslots; i++) {
3771 			dr->getdesc(dr, i, &desc, &mt);
3772 
3773 			error = bus_dmamap_create(dma->rxbuf_dtag, 0,
3774 			    &mt->mt_dmap);
3775 			if (error) {
3776 				device_printf(sc->sc_dev,
3777 				    "can't create RX buf DMA map\n");
3778 				goto out;	/* XXX wrong! */
3779 			}
3780 			error = bwn_dma_newbuf(dr, desc, mt, 1);
3781 			if (error) {
3782 				device_printf(sc->sc_dev,
3783 				    "failed to allocate RX buf\n");
3784 				goto out;	/* XXX wrong! */
3785 			}
3786 		}
3787 
3788 		bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
3789 		    BUS_DMASYNC_PREWRITE);
3790 
3791 		dr->dr_usedslot = dr->dr_numslots;
3792 	}
3793 
3794       out:
3795 	return (dr);
3796 
3797 fail2:
3798 	free(dr->dr_txhdr_cache, M_DEVBUF);
3799 fail1:
3800 	free(dr->dr_meta, M_DEVBUF);
3801 fail0:
3802 	free(dr, M_DEVBUF);
3803 	return (NULL);
3804 }
3805 
3806 static void
3807 bwn_dma_ringfree(struct bwn_dma_ring **dr)
3808 {
3809 
3810 	if (dr == NULL)
3811 		return;
3812 
3813 	bwn_dma_free_descbufs(*dr);
3814 	bwn_dma_free_ringmemory(*dr);
3815 
3816 	free((*dr)->dr_txhdr_cache, M_DEVBUF);
3817 	free((*dr)->dr_meta, M_DEVBUF);
3818 	free(*dr, M_DEVBUF);
3819 
3820 	*dr = NULL;
3821 }
3822 
3823 static void
3824 bwn_dma_32_getdesc(struct bwn_dma_ring *dr, int slot,
3825     struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3826 {
3827 	struct bwn_dmadesc32 *desc;
3828 
3829 	*meta = &(dr->dr_meta[slot]);
3830 	desc = dr->dr_ring_descbase;
3831 	desc = &(desc[slot]);
3832 
3833 	*gdesc = (struct bwn_dmadesc_generic *)desc;
3834 }
3835 
3836 static void
3837 bwn_dma_32_setdesc(struct bwn_dma_ring *dr,
3838     struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3839     int start, int end, int irq)
3840 {
3841 	struct bwn_dmadesc32 *descbase = dr->dr_ring_descbase;
3842 	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3843 	uint32_t addr, addrext, ctl;
3844 	int slot;
3845 
3846 	slot = (int)(&(desc->dma.dma32) - descbase);
3847 	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3848 	    ("%s:%d: fail", __func__, __LINE__));
3849 
3850 	addr = (uint32_t) (dmaaddr & ~SIBA_DMA_TRANSLATION_MASK);
3851 	addrext = (uint32_t) (dmaaddr & SIBA_DMA_TRANSLATION_MASK) >> 30;
3852 	addr |= siba_dma_translation(sc->sc_dev);
3853 	ctl = bufsize & BWN_DMA32_DCTL_BYTECNT;
3854 	if (slot == dr->dr_numslots - 1)
3855 		ctl |= BWN_DMA32_DCTL_DTABLEEND;
3856 	if (start)
3857 		ctl |= BWN_DMA32_DCTL_FRAMESTART;
3858 	if (end)
3859 		ctl |= BWN_DMA32_DCTL_FRAMEEND;
3860 	if (irq)
3861 		ctl |= BWN_DMA32_DCTL_IRQ;
3862 	ctl |= (addrext << BWN_DMA32_DCTL_ADDREXT_SHIFT)
3863 	    & BWN_DMA32_DCTL_ADDREXT_MASK;
3864 
3865 	desc->dma.dma32.control = htole32(ctl);
3866 	desc->dma.dma32.address = htole32(addr);
3867 }
3868 
3869 static void
3870 bwn_dma_32_start_transfer(struct bwn_dma_ring *dr, int slot)
3871 {
3872 
3873 	BWN_DMA_WRITE(dr, BWN_DMA32_TXINDEX,
3874 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc32)));
3875 }
3876 
3877 static void
3878 bwn_dma_32_suspend(struct bwn_dma_ring *dr)
3879 {
3880 
3881 	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3882 	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) | BWN_DMA32_TXSUSPEND);
3883 }
3884 
3885 static void
3886 bwn_dma_32_resume(struct bwn_dma_ring *dr)
3887 {
3888 
3889 	BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL,
3890 	    BWN_DMA_READ(dr, BWN_DMA32_TXCTL) & ~BWN_DMA32_TXSUSPEND);
3891 }
3892 
3893 static int
3894 bwn_dma_32_get_curslot(struct bwn_dma_ring *dr)
3895 {
3896 	uint32_t val;
3897 
3898 	val = BWN_DMA_READ(dr, BWN_DMA32_RXSTATUS);
3899 	val &= BWN_DMA32_RXDPTR;
3900 
3901 	return (val / sizeof(struct bwn_dmadesc32));
3902 }
3903 
3904 static void
3905 bwn_dma_32_set_curslot(struct bwn_dma_ring *dr, int slot)
3906 {
3907 
3908 	BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX,
3909 	    (uint32_t) (slot * sizeof(struct bwn_dmadesc32)));
3910 }
3911 
3912 static void
3913 bwn_dma_64_getdesc(struct bwn_dma_ring *dr, int slot,
3914     struct bwn_dmadesc_generic **gdesc, struct bwn_dmadesc_meta **meta)
3915 {
3916 	struct bwn_dmadesc64 *desc;
3917 
3918 	*meta = &(dr->dr_meta[slot]);
3919 	desc = dr->dr_ring_descbase;
3920 	desc = &(desc[slot]);
3921 
3922 	*gdesc = (struct bwn_dmadesc_generic *)desc;
3923 }
3924 
3925 static void
3926 bwn_dma_64_setdesc(struct bwn_dma_ring *dr,
3927     struct bwn_dmadesc_generic *desc, bus_addr_t dmaaddr, uint16_t bufsize,
3928     int start, int end, int irq)
3929 {
3930 	struct bwn_dmadesc64 *descbase = dr->dr_ring_descbase;
3931 	struct bwn_softc *sc = dr->dr_mac->mac_sc;
3932 	int slot;
3933 	uint32_t ctl0 = 0, ctl1 = 0;
3934 	uint32_t addrlo, addrhi;
3935 	uint32_t addrext;
3936 
3937 	slot = (int)(&(desc->dma.dma64) - descbase);
3938 	KASSERT(slot >= 0 && slot < dr->dr_numslots,
3939 	    ("%s:%d: fail", __func__, __LINE__));
3940 
3941 	addrlo = (uint32_t) (dmaaddr & 0xffffffff);
3942 	addrhi = (((uint64_t) dmaaddr >> 32) & ~SIBA_DMA_TRANSLATION_MASK);
3943 	addrext = (((uint64_t) dmaaddr >> 32) & SIBA_DMA_TRANSLATION_MASK) >>
3944 	    30;
3945 	addrhi |= (siba_dma_translation(sc->sc_dev) << 1);
3946 	if (slot == dr->dr_numslots - 1)
3947 		ctl0 |= BWN_DMA64_DCTL0_DTABLEEND;
3948 	if (start)
3949 		ctl0 |= BWN_DMA64_DCTL0_FRAMESTART;
3950 	if (end)
3951 		ctl0 |= BWN_DMA64_DCTL0_FRAMEEND;
3952 	if (irq)
3953 		ctl0 |= BWN_DMA64_DCTL0_IRQ;
3954 	ctl1 |= bufsize & BWN_DMA64_DCTL1_BYTECNT;
3955 	ctl1 |= (addrext << BWN_DMA64_DCTL1_ADDREXT_SHIFT)
3956 	    & BWN_DMA64_DCTL1_ADDREXT_MASK;
3957 
3958 	desc->dma.dma64.control0 = htole32(ctl0);
3959 	desc->dma.dma64.control1 = htole32(ctl1);
3960 	desc->dma.dma64.address_low = htole32(addrlo);
3961 	desc->dma.dma64.address_high = htole32(addrhi);
3962 }
3963 
3964 static void
3965 bwn_dma_64_start_transfer(struct bwn_dma_ring *dr, int slot)
3966 {
3967 
3968 	BWN_DMA_WRITE(dr, BWN_DMA64_TXINDEX,
3969 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
3970 }
3971 
3972 static void
3973 bwn_dma_64_suspend(struct bwn_dma_ring *dr)
3974 {
3975 
3976 	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
3977 	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) | BWN_DMA64_TXSUSPEND);
3978 }
3979 
3980 static void
3981 bwn_dma_64_resume(struct bwn_dma_ring *dr)
3982 {
3983 
3984 	BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL,
3985 	    BWN_DMA_READ(dr, BWN_DMA64_TXCTL) & ~BWN_DMA64_TXSUSPEND);
3986 }
3987 
3988 static int
3989 bwn_dma_64_get_curslot(struct bwn_dma_ring *dr)
3990 {
3991 	uint32_t val;
3992 
3993 	val = BWN_DMA_READ(dr, BWN_DMA64_RXSTATUS);
3994 	val &= BWN_DMA64_RXSTATDPTR;
3995 
3996 	return (val / sizeof(struct bwn_dmadesc64));
3997 }
3998 
3999 static void
4000 bwn_dma_64_set_curslot(struct bwn_dma_ring *dr, int slot)
4001 {
4002 
4003 	BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX,
4004 	    (uint32_t)(slot * sizeof(struct bwn_dmadesc64)));
4005 }
4006 
4007 static int
4008 bwn_dma_allocringmemory(struct bwn_dma_ring *dr)
4009 {
4010 	struct bwn_mac *mac = dr->dr_mac;
4011 	struct bwn_dma *dma = &mac->mac_method.dma;
4012 	struct bwn_softc *sc = mac->mac_sc;
4013 	int error;
4014 
4015 	error = bus_dma_tag_create(dma->parent_dtag,
4016 			    BWN_ALIGN, 0,
4017 			    BUS_SPACE_MAXADDR,
4018 			    BUS_SPACE_MAXADDR,
4019 			    NULL, NULL,
4020 			    BWN_DMA_RINGMEMSIZE,
4021 			    1,
4022 			    BUS_SPACE_MAXSIZE_32BIT,
4023 			    0,
4024 			    NULL, NULL,
4025 			    &dr->dr_ring_dtag);
4026 	if (error) {
4027 		device_printf(sc->sc_dev,
4028 		    "can't create TX ring DMA tag: TODO frees\n");
4029 		return (-1);
4030 	}
4031 
4032 	error = bus_dmamem_alloc(dr->dr_ring_dtag,
4033 	    &dr->dr_ring_descbase, BUS_DMA_WAITOK | BUS_DMA_ZERO,
4034 	    &dr->dr_ring_dmap);
4035 	if (error) {
4036 		device_printf(sc->sc_dev,
4037 		    "can't allocate DMA mem: TODO frees\n");
4038 		return (-1);
4039 	}
4040 	error = bus_dmamap_load(dr->dr_ring_dtag, dr->dr_ring_dmap,
4041 	    dr->dr_ring_descbase, BWN_DMA_RINGMEMSIZE,
4042 	    bwn_dma_ring_addr, &dr->dr_ring_dmabase, BUS_DMA_NOWAIT);
4043 	if (error) {
4044 		device_printf(sc->sc_dev,
4045 		    "can't load DMA mem: TODO free\n");
4046 		return (-1);
4047 	}
4048 
4049 	return (0);
4050 }
4051 
4052 static void
4053 bwn_dma_setup(struct bwn_dma_ring *dr)
4054 {
4055 	struct bwn_softc *sc = dr->dr_mac->mac_sc;
4056 	uint64_t ring64;
4057 	uint32_t addrext, ring32, value;
4058 	uint32_t trans = siba_dma_translation(sc->sc_dev);
4059 
4060 	if (dr->dr_tx) {
4061 		dr->dr_curslot = -1;
4062 
4063 		if (dr->dr_type == BWN_DMA_64BIT) {
4064 			ring64 = (uint64_t)(dr->dr_ring_dmabase);
4065 			addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK)
4066 			    >> 30;
4067 			value = BWN_DMA64_TXENABLE;
4068 			value |= (addrext << BWN_DMA64_TXADDREXT_SHIFT)
4069 			    & BWN_DMA64_TXADDREXT_MASK;
4070 			BWN_DMA_WRITE(dr, BWN_DMA64_TXCTL, value);
4071 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO,
4072 			    (ring64 & 0xffffffff));
4073 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI,
4074 			    ((ring64 >> 32) &
4075 			    ~SIBA_DMA_TRANSLATION_MASK) | (trans << 1));
4076 		} else {
4077 			ring32 = (uint32_t)(dr->dr_ring_dmabase);
4078 			addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4079 			value = BWN_DMA32_TXENABLE;
4080 			value |= (addrext << BWN_DMA32_TXADDREXT_SHIFT)
4081 			    & BWN_DMA32_TXADDREXT_MASK;
4082 			BWN_DMA_WRITE(dr, BWN_DMA32_TXCTL, value);
4083 			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING,
4084 			    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4085 		}
4086 		return;
4087 	}
4088 
4089 	/*
4090 	 * set for RX
4091 	 */
4092 	dr->dr_usedslot = dr->dr_numslots;
4093 
4094 	if (dr->dr_type == BWN_DMA_64BIT) {
4095 		ring64 = (uint64_t)(dr->dr_ring_dmabase);
4096 		addrext = ((ring64 >> 32) & SIBA_DMA_TRANSLATION_MASK) >> 30;
4097 		value = (dr->dr_frameoffset << BWN_DMA64_RXFROFF_SHIFT);
4098 		value |= BWN_DMA64_RXENABLE;
4099 		value |= (addrext << BWN_DMA64_RXADDREXT_SHIFT)
4100 		    & BWN_DMA64_RXADDREXT_MASK;
4101 		BWN_DMA_WRITE(dr, BWN_DMA64_RXCTL, value);
4102 		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, (ring64 & 0xffffffff));
4103 		BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI,
4104 		    ((ring64 >> 32) & ~SIBA_DMA_TRANSLATION_MASK)
4105 		    | (trans << 1));
4106 		BWN_DMA_WRITE(dr, BWN_DMA64_RXINDEX, dr->dr_numslots *
4107 		    sizeof(struct bwn_dmadesc64));
4108 	} else {
4109 		ring32 = (uint32_t)(dr->dr_ring_dmabase);
4110 		addrext = (ring32 & SIBA_DMA_TRANSLATION_MASK) >> 30;
4111 		value = (dr->dr_frameoffset << BWN_DMA32_RXFROFF_SHIFT);
4112 		value |= BWN_DMA32_RXENABLE;
4113 		value |= (addrext << BWN_DMA32_RXADDREXT_SHIFT)
4114 		    & BWN_DMA32_RXADDREXT_MASK;
4115 		BWN_DMA_WRITE(dr, BWN_DMA32_RXCTL, value);
4116 		BWN_DMA_WRITE(dr, BWN_DMA32_RXRING,
4117 		    (ring32 & ~SIBA_DMA_TRANSLATION_MASK) | trans);
4118 		BWN_DMA_WRITE(dr, BWN_DMA32_RXINDEX, dr->dr_numslots *
4119 		    sizeof(struct bwn_dmadesc32));
4120 	}
4121 }
4122 
4123 static void
4124 bwn_dma_free_ringmemory(struct bwn_dma_ring *dr)
4125 {
4126 
4127 	bus_dmamap_unload(dr->dr_ring_dtag, dr->dr_ring_dmap);
4128 	bus_dmamem_free(dr->dr_ring_dtag, dr->dr_ring_descbase,
4129 	    dr->dr_ring_dmap);
4130 }
4131 
4132 static void
4133 bwn_dma_cleanup(struct bwn_dma_ring *dr)
4134 {
4135 
4136 	if (dr->dr_tx) {
4137 		bwn_dma_tx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4138 		if (dr->dr_type == BWN_DMA_64BIT) {
4139 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGLO, 0);
4140 			BWN_DMA_WRITE(dr, BWN_DMA64_TXRINGHI, 0);
4141 		} else
4142 			BWN_DMA_WRITE(dr, BWN_DMA32_TXRING, 0);
4143 	} else {
4144 		bwn_dma_rx_reset(dr->dr_mac, dr->dr_base, dr->dr_type);
4145 		if (dr->dr_type == BWN_DMA_64BIT) {
4146 			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGLO, 0);
4147 			BWN_DMA_WRITE(dr, BWN_DMA64_RXRINGHI, 0);
4148 		} else
4149 			BWN_DMA_WRITE(dr, BWN_DMA32_RXRING, 0);
4150 	}
4151 }
4152 
4153 static void
4154 bwn_dma_free_descbufs(struct bwn_dma_ring *dr)
4155 {
4156 	struct bwn_dmadesc_generic *desc;
4157 	struct bwn_dmadesc_meta *meta;
4158 	struct bwn_mac *mac = dr->dr_mac;
4159 	struct bwn_dma *dma = &mac->mac_method.dma;
4160 	struct bwn_softc *sc = mac->mac_sc;
4161 	int i;
4162 
4163 	if (!dr->dr_usedslot)
4164 		return;
4165 	for (i = 0; i < dr->dr_numslots; i++) {
4166 		dr->getdesc(dr, i, &desc, &meta);
4167 
4168 		if (meta->mt_m == NULL) {
4169 			if (!dr->dr_tx)
4170 				device_printf(sc->sc_dev, "%s: not TX?\n",
4171 				    __func__);
4172 			continue;
4173 		}
4174 		if (dr->dr_tx) {
4175 			if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
4176 				bus_dmamap_unload(dr->dr_txring_dtag,
4177 				    meta->mt_dmap);
4178 			else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
4179 				bus_dmamap_unload(dma->txbuf_dtag,
4180 				    meta->mt_dmap);
4181 		} else
4182 			bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
4183 		bwn_dma_free_descbuf(dr, meta);
4184 	}
4185 }
4186 
4187 static int
4188 bwn_dma_tx_reset(struct bwn_mac *mac, uint16_t base,
4189     int type)
4190 {
4191 	struct bwn_softc *sc = mac->mac_sc;
4192 	uint32_t value;
4193 	int i;
4194 	uint16_t offset;
4195 
4196 	for (i = 0; i < 10; i++) {
4197 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4198 		    BWN_DMA32_TXSTATUS;
4199 		value = BWN_READ_4(mac, base + offset);
4200 		if (type == BWN_DMA_64BIT) {
4201 			value &= BWN_DMA64_TXSTAT;
4202 			if (value == BWN_DMA64_TXSTAT_DISABLED ||
4203 			    value == BWN_DMA64_TXSTAT_IDLEWAIT ||
4204 			    value == BWN_DMA64_TXSTAT_STOPPED)
4205 				break;
4206 		} else {
4207 			value &= BWN_DMA32_TXSTATE;
4208 			if (value == BWN_DMA32_TXSTAT_DISABLED ||
4209 			    value == BWN_DMA32_TXSTAT_IDLEWAIT ||
4210 			    value == BWN_DMA32_TXSTAT_STOPPED)
4211 				break;
4212 		}
4213 		DELAY(1000);
4214 	}
4215 	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXCTL : BWN_DMA32_TXCTL;
4216 	BWN_WRITE_4(mac, base + offset, 0);
4217 	for (i = 0; i < 10; i++) {
4218 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_TXSTATUS :
4219 						   BWN_DMA32_TXSTATUS;
4220 		value = BWN_READ_4(mac, base + offset);
4221 		if (type == BWN_DMA_64BIT) {
4222 			value &= BWN_DMA64_TXSTAT;
4223 			if (value == BWN_DMA64_TXSTAT_DISABLED) {
4224 				i = -1;
4225 				break;
4226 			}
4227 		} else {
4228 			value &= BWN_DMA32_TXSTATE;
4229 			if (value == BWN_DMA32_TXSTAT_DISABLED) {
4230 				i = -1;
4231 				break;
4232 			}
4233 		}
4234 		DELAY(1000);
4235 	}
4236 	if (i != -1) {
4237 		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4238 		return (ENODEV);
4239 	}
4240 	DELAY(1000);
4241 
4242 	return (0);
4243 }
4244 
4245 static int
4246 bwn_dma_rx_reset(struct bwn_mac *mac, uint16_t base,
4247     int type)
4248 {
4249 	struct bwn_softc *sc = mac->mac_sc;
4250 	uint32_t value;
4251 	int i;
4252 	uint16_t offset;
4253 
4254 	offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXCTL : BWN_DMA32_RXCTL;
4255 	BWN_WRITE_4(mac, base + offset, 0);
4256 	for (i = 0; i < 10; i++) {
4257 		offset = (type == BWN_DMA_64BIT) ? BWN_DMA64_RXSTATUS :
4258 		    BWN_DMA32_RXSTATUS;
4259 		value = BWN_READ_4(mac, base + offset);
4260 		if (type == BWN_DMA_64BIT) {
4261 			value &= BWN_DMA64_RXSTAT;
4262 			if (value == BWN_DMA64_RXSTAT_DISABLED) {
4263 				i = -1;
4264 				break;
4265 			}
4266 		} else {
4267 			value &= BWN_DMA32_RXSTATE;
4268 			if (value == BWN_DMA32_RXSTAT_DISABLED) {
4269 				i = -1;
4270 				break;
4271 			}
4272 		}
4273 		DELAY(1000);
4274 	}
4275 	if (i != -1) {
4276 		device_printf(sc->sc_dev, "%s: timed out\n", __func__);
4277 		return (ENODEV);
4278 	}
4279 
4280 	return (0);
4281 }
4282 
4283 static void
4284 bwn_dma_free_descbuf(struct bwn_dma_ring *dr,
4285     struct bwn_dmadesc_meta *meta)
4286 {
4287 
4288 	if (meta->mt_m != NULL) {
4289 		m_freem(meta->mt_m);
4290 		meta->mt_m = NULL;
4291 	}
4292 	if (meta->mt_ni != NULL) {
4293 		ieee80211_free_node(meta->mt_ni);
4294 		meta->mt_ni = NULL;
4295 	}
4296 }
4297 
4298 static void
4299 bwn_dma_set_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4300 {
4301 	struct bwn_rxhdr4 *rxhdr;
4302 	unsigned char *frame;
4303 
4304 	rxhdr = mtod(m, struct bwn_rxhdr4 *);
4305 	rxhdr->frame_len = 0;
4306 
4307 	KASSERT(dr->dr_rx_bufsize >= dr->dr_frameoffset +
4308 	    sizeof(struct bwn_plcp6) + 2,
4309 	    ("%s:%d: fail", __func__, __LINE__));
4310 	frame = mtod(m, char *) + dr->dr_frameoffset;
4311 	memset(frame, 0xff, sizeof(struct bwn_plcp6) + 2 /* padding */);
4312 }
4313 
4314 static uint8_t
4315 bwn_dma_check_redzone(struct bwn_dma_ring *dr, struct mbuf *m)
4316 {
4317 	unsigned char *f = mtod(m, char *) + dr->dr_frameoffset;
4318 
4319 	return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7])
4320 	    == 0xff);
4321 }
4322 
4323 static void
4324 bwn_wme_init(struct bwn_mac *mac)
4325 {
4326 
4327 	bwn_wme_load(mac);
4328 
4329 	/* enable WME support. */
4330 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_EDCF);
4331 	BWN_WRITE_2(mac, BWN_IFSCTL, BWN_READ_2(mac, BWN_IFSCTL) |
4332 	    BWN_IFSCTL_USE_EDCF);
4333 }
4334 
4335 static void
4336 bwn_spu_setdelay(struct bwn_mac *mac, int idle)
4337 {
4338 	struct bwn_softc *sc = mac->mac_sc;
4339 	struct ieee80211com *ic = &sc->sc_ic;
4340 	uint16_t delay;	/* microsec */
4341 
4342 	delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
4343 	if (ic->ic_opmode == IEEE80211_M_IBSS || idle)
4344 		delay = 500;
4345 	if ((mac->mac_phy.rf_ver == 0x2050) && (mac->mac_phy.rf_rev == 8))
4346 		delay = max(delay, (uint16_t)2400);
4347 
4348 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_SPU_WAKEUP, delay);
4349 }
4350 
4351 static void
4352 bwn_bt_enable(struct bwn_mac *mac)
4353 {
4354 	struct bwn_softc *sc = mac->mac_sc;
4355 	uint64_t hf;
4356 
4357 	if (bwn_bluetooth == 0)
4358 		return;
4359 	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCOEXIST) == 0)
4360 		return;
4361 	if (mac->mac_phy.type != BWN_PHYTYPE_B && !mac->mac_phy.gmode)
4362 		return;
4363 
4364 	hf = bwn_hf_read(mac);
4365 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_BTCMOD)
4366 		hf |= BWN_HF_BT_COEXISTALT;
4367 	else
4368 		hf |= BWN_HF_BT_COEXIST;
4369 	bwn_hf_write(mac, hf);
4370 }
4371 
4372 static void
4373 bwn_set_macaddr(struct bwn_mac *mac)
4374 {
4375 
4376 	bwn_mac_write_bssid(mac);
4377 	bwn_mac_setfilter(mac, BWN_MACFILTER_SELF,
4378 	    mac->mac_sc->sc_ic.ic_macaddr);
4379 }
4380 
4381 static void
4382 bwn_clear_keys(struct bwn_mac *mac)
4383 {
4384 	int i;
4385 
4386 	for (i = 0; i < mac->mac_max_nr_keys; i++) {
4387 		KASSERT(i >= 0 && i < mac->mac_max_nr_keys,
4388 		    ("%s:%d: fail", __func__, __LINE__));
4389 
4390 		bwn_key_dowrite(mac, i, BWN_SEC_ALGO_NONE,
4391 		    NULL, BWN_SEC_KEYSIZE, NULL);
4392 		if ((i <= 3) && !BWN_SEC_NEWAPI(mac)) {
4393 			bwn_key_dowrite(mac, i + 4, BWN_SEC_ALGO_NONE,
4394 			    NULL, BWN_SEC_KEYSIZE, NULL);
4395 		}
4396 		mac->mac_key[i].keyconf = NULL;
4397 	}
4398 }
4399 
4400 static void
4401 bwn_crypt_init(struct bwn_mac *mac)
4402 {
4403 	struct bwn_softc *sc = mac->mac_sc;
4404 
4405 	mac->mac_max_nr_keys = (siba_get_revid(sc->sc_dev) >= 5) ? 58 : 20;
4406 	KASSERT(mac->mac_max_nr_keys <= N(mac->mac_key),
4407 	    ("%s:%d: fail", __func__, __LINE__));
4408 	mac->mac_ktp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_KEY_TABLEP);
4409 	mac->mac_ktp *= 2;
4410 	if (siba_get_revid(sc->sc_dev) >= 5)
4411 		BWN_WRITE_2(mac, BWN_RCMTA_COUNT, mac->mac_max_nr_keys - 8);
4412 	bwn_clear_keys(mac);
4413 }
4414 
4415 static void
4416 bwn_chip_exit(struct bwn_mac *mac)
4417 {
4418 	struct bwn_softc *sc = mac->mac_sc;
4419 
4420 	bwn_phy_exit(mac);
4421 	siba_gpio_set(sc->sc_dev, 0);
4422 }
4423 
4424 static int
4425 bwn_fw_fillinfo(struct bwn_mac *mac)
4426 {
4427 	int error;
4428 
4429 	error = bwn_fw_gets(mac, BWN_FWTYPE_DEFAULT);
4430 	if (error == 0)
4431 		return (0);
4432 	error = bwn_fw_gets(mac, BWN_FWTYPE_OPENSOURCE);
4433 	if (error == 0)
4434 		return (0);
4435 	return (error);
4436 }
4437 
4438 static int
4439 bwn_gpio_init(struct bwn_mac *mac)
4440 {
4441 	struct bwn_softc *sc = mac->mac_sc;
4442 	uint32_t mask = 0x1f, set = 0xf, value;
4443 
4444 	BWN_WRITE_4(mac, BWN_MACCTL,
4445 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_GPOUT_MASK);
4446 	BWN_WRITE_2(mac, BWN_GPIO_MASK,
4447 	    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x000f);
4448 
4449 	if (siba_get_chipid(sc->sc_dev) == 0x4301) {
4450 		mask |= 0x0060;
4451 		set |= 0x0060;
4452 	}
4453 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL) {
4454 		BWN_WRITE_2(mac, BWN_GPIO_MASK,
4455 		    BWN_READ_2(mac, BWN_GPIO_MASK) | 0x0200);
4456 		mask |= 0x0200;
4457 		set |= 0x0200;
4458 	}
4459 	if (siba_get_revid(sc->sc_dev) >= 2)
4460 		mask |= 0x0010;
4461 
4462 	value = siba_gpio_get(sc->sc_dev);
4463 	if (value == -1)
4464 		return (0);
4465 	siba_gpio_set(sc->sc_dev, (value & mask) | set);
4466 
4467 	return (0);
4468 }
4469 
4470 static int
4471 bwn_fw_loadinitvals(struct bwn_mac *mac)
4472 {
4473 #define	GETFWOFFSET(fwp, offset)				\
4474 	((const struct bwn_fwinitvals *)((const char *)fwp.fw->data + offset))
4475 	const size_t hdr_len = sizeof(struct bwn_fwhdr);
4476 	const struct bwn_fwhdr *hdr;
4477 	struct bwn_fw *fw = &mac->mac_fw;
4478 	int error;
4479 
4480 	hdr = (const struct bwn_fwhdr *)(fw->initvals.fw->data);
4481 	error = bwn_fwinitvals_write(mac, GETFWOFFSET(fw->initvals, hdr_len),
4482 	    be32toh(hdr->size), fw->initvals.fw->datasize - hdr_len);
4483 	if (error)
4484 		return (error);
4485 	if (fw->initvals_band.fw) {
4486 		hdr = (const struct bwn_fwhdr *)(fw->initvals_band.fw->data);
4487 		error = bwn_fwinitvals_write(mac,
4488 		    GETFWOFFSET(fw->initvals_band, hdr_len),
4489 		    be32toh(hdr->size),
4490 		    fw->initvals_band.fw->datasize - hdr_len);
4491 	}
4492 	return (error);
4493 #undef GETFWOFFSET
4494 }
4495 
4496 static int
4497 bwn_phy_init(struct bwn_mac *mac)
4498 {
4499 	struct bwn_softc *sc = mac->mac_sc;
4500 	int error;
4501 
4502 	mac->mac_phy.chan = mac->mac_phy.get_default_chan(mac);
4503 	mac->mac_phy.rf_onoff(mac, 1);
4504 	error = mac->mac_phy.init(mac);
4505 	if (error) {
4506 		device_printf(sc->sc_dev, "PHY init failed\n");
4507 		goto fail0;
4508 	}
4509 	error = bwn_switch_channel(mac,
4510 	    mac->mac_phy.get_default_chan(mac));
4511 	if (error) {
4512 		device_printf(sc->sc_dev,
4513 		    "failed to switch default channel\n");
4514 		goto fail1;
4515 	}
4516 	return (0);
4517 fail1:
4518 	if (mac->mac_phy.exit)
4519 		mac->mac_phy.exit(mac);
4520 fail0:
4521 	mac->mac_phy.rf_onoff(mac, 0);
4522 
4523 	return (error);
4524 }
4525 
4526 static void
4527 bwn_set_txantenna(struct bwn_mac *mac, int antenna)
4528 {
4529 	uint16_t ant;
4530 	uint16_t tmp;
4531 
4532 	ant = bwn_ant2phy(antenna);
4533 
4534 	/* For ACK/CTS */
4535 	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL);
4536 	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4537 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_ACKCTS_PHYCTL, tmp);
4538 	/* For Probe Resposes */
4539 	tmp = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL);
4540 	tmp = (tmp & ~BWN_TX_PHY_ANT) | ant;
4541 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PROBE_RESP_PHYCTL, tmp);
4542 }
4543 
4544 static void
4545 bwn_set_opmode(struct bwn_mac *mac)
4546 {
4547 	struct bwn_softc *sc = mac->mac_sc;
4548 	struct ieee80211com *ic = &sc->sc_ic;
4549 	uint32_t ctl;
4550 	uint16_t cfp_pretbtt;
4551 
4552 	ctl = BWN_READ_4(mac, BWN_MACCTL);
4553 	ctl &= ~(BWN_MACCTL_HOSTAP | BWN_MACCTL_PASS_CTL |
4554 	    BWN_MACCTL_PASS_BADPLCP | BWN_MACCTL_PASS_BADFCS |
4555 	    BWN_MACCTL_PROMISC | BWN_MACCTL_BEACON_PROMISC);
4556 	ctl |= BWN_MACCTL_STA;
4557 
4558 	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
4559 	    ic->ic_opmode == IEEE80211_M_MBSS)
4560 		ctl |= BWN_MACCTL_HOSTAP;
4561 	else if (ic->ic_opmode == IEEE80211_M_IBSS)
4562 		ctl &= ~BWN_MACCTL_STA;
4563 	ctl |= sc->sc_filters;
4564 
4565 	if (siba_get_revid(sc->sc_dev) <= 4)
4566 		ctl |= BWN_MACCTL_PROMISC;
4567 
4568 	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
4569 
4570 	cfp_pretbtt = 2;
4571 	if ((ctl & BWN_MACCTL_STA) && !(ctl & BWN_MACCTL_HOSTAP)) {
4572 		if (siba_get_chipid(sc->sc_dev) == 0x4306 &&
4573 		    siba_get_chiprev(sc->sc_dev) == 3)
4574 			cfp_pretbtt = 100;
4575 		else
4576 			cfp_pretbtt = 50;
4577 	}
4578 	BWN_WRITE_2(mac, 0x612, cfp_pretbtt);
4579 }
4580 
4581 static int
4582 bwn_dma_gettype(struct bwn_mac *mac)
4583 {
4584 	uint32_t tmp;
4585 	uint16_t base;
4586 
4587 	tmp = BWN_READ_4(mac, SIBA_TGSHIGH);
4588 	if (tmp & SIBA_TGSHIGH_DMA64)
4589 		return (BWN_DMA_64BIT);
4590 	base = bwn_dma_base(0, 0);
4591 	BWN_WRITE_4(mac, base + BWN_DMA32_TXCTL, BWN_DMA32_TXADDREXT_MASK);
4592 	tmp = BWN_READ_4(mac, base + BWN_DMA32_TXCTL);
4593 	if (tmp & BWN_DMA32_TXADDREXT_MASK)
4594 		return (BWN_DMA_32BIT);
4595 
4596 	return (BWN_DMA_30BIT);
4597 }
4598 
4599 static void
4600 bwn_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error)
4601 {
4602 	if (!error) {
4603 		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
4604 		*((bus_addr_t *)arg) = seg->ds_addr;
4605 	}
4606 }
4607 
4608 static void
4609 bwn_phy_g_init_sub(struct bwn_mac *mac)
4610 {
4611 	struct bwn_phy *phy = &mac->mac_phy;
4612 	struct bwn_phy_g *pg = &phy->phy_g;
4613 	struct bwn_softc *sc = mac->mac_sc;
4614 	uint16_t i, tmp;
4615 
4616 	if (phy->rev == 1)
4617 		bwn_phy_init_b5(mac);
4618 	else
4619 		bwn_phy_init_b6(mac);
4620 
4621 	if (phy->rev >= 2 || phy->gmode)
4622 		bwn_phy_init_a(mac);
4623 
4624 	if (phy->rev >= 2) {
4625 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, 0);
4626 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, 0);
4627 	}
4628 	if (phy->rev == 2) {
4629 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
4630 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4631 	}
4632 	if (phy->rev > 5) {
4633 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x400);
4634 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xc0);
4635 	}
4636 	if (phy->gmode || phy->rev >= 2) {
4637 		tmp = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
4638 		tmp &= BWN_PHYVER_VERSION;
4639 		if (tmp == 3 || tmp == 5) {
4640 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc2), 0x1816);
4641 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc3), 0x8006);
4642 		}
4643 		if (tmp == 5) {
4644 			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xcc), 0x00ff,
4645 			    0x1f00);
4646 		}
4647 	}
4648 	if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2)
4649 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x7e), 0x78);
4650 	if (phy->rf_rev == 8) {
4651 		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x80);
4652 		BWN_PHY_SET(mac, BWN_PHY_OFDM(0x3e), 0x4);
4653 	}
4654 	if (BWN_HAS_LOOPBACK(phy))
4655 		bwn_loopback_calcgain(mac);
4656 
4657 	if (phy->rf_rev != 8) {
4658 		if (pg->pg_initval == 0xffff)
4659 			pg->pg_initval = bwn_rf_init_bcm2050(mac);
4660 		else
4661 			BWN_RF_WRITE(mac, 0x0078, pg->pg_initval);
4662 	}
4663 	bwn_lo_g_init(mac);
4664 	if (BWN_HAS_TXMAG(phy)) {
4665 		BWN_RF_WRITE(mac, 0x52,
4666 		    (BWN_RF_READ(mac, 0x52) & 0xff00)
4667 		    | pg->pg_loctl.tx_bias |
4668 		    pg->pg_loctl.tx_magn);
4669 	} else {
4670 		BWN_RF_SETMASK(mac, 0x52, 0xfff0, pg->pg_loctl.tx_bias);
4671 	}
4672 	if (phy->rev >= 6) {
4673 		BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x36), 0x0fff,
4674 		    (pg->pg_loctl.tx_bias << 12));
4675 	}
4676 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL)
4677 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8075);
4678 	else
4679 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x807f);
4680 	if (phy->rev < 2)
4681 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x101);
4682 	else
4683 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x202);
4684 	if (phy->gmode || phy->rev >= 2) {
4685 		bwn_lo_g_adjust(mac);
4686 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
4687 	}
4688 
4689 	if (!(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
4690 		for (i = 0; i < 64; i++) {
4691 			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, i);
4692 			BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_DATA,
4693 			    (uint16_t)MIN(MAX(bwn_nrssi_read(mac, i) - 0xffff,
4694 			    -32), 31));
4695 		}
4696 		bwn_nrssi_threshold(mac);
4697 	} else if (phy->gmode || phy->rev >= 2) {
4698 		if (pg->pg_nrssi[0] == -1000) {
4699 			KASSERT(pg->pg_nrssi[1] == -1000,
4700 			    ("%s:%d: fail", __func__, __LINE__));
4701 			bwn_nrssi_slope_11g(mac);
4702 		} else
4703 			bwn_nrssi_threshold(mac);
4704 	}
4705 	if (phy->rf_rev == 8)
4706 		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x05), 0x3230);
4707 	bwn_phy_hwpctl_init(mac);
4708 	if ((siba_get_chipid(sc->sc_dev) == 0x4306
4709 	     && siba_get_chippkg(sc->sc_dev) == 2) || 0) {
4710 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0xbfff);
4711 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xc3), 0x7fff);
4712 	}
4713 }
4714 
4715 static uint8_t
4716 bwn_has_hwpctl(struct bwn_mac *mac)
4717 {
4718 
4719 	if (mac->mac_phy.hwpctl == 0 || mac->mac_phy.use_hwpctl == NULL)
4720 		return (0);
4721 	return (mac->mac_phy.use_hwpctl(mac));
4722 }
4723 
4724 static void
4725 bwn_phy_init_b5(struct bwn_mac *mac)
4726 {
4727 	struct bwn_phy *phy = &mac->mac_phy;
4728 	struct bwn_phy_g *pg = &phy->phy_g;
4729 	struct bwn_softc *sc = mac->mac_sc;
4730 	uint16_t offset, value;
4731 	uint8_t old_channel;
4732 
4733 	if (phy->analog == 1)
4734 		BWN_RF_SET(mac, 0x007a, 0x0050);
4735 	if ((siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM) &&
4736 	    (siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306)) {
4737 		value = 0x2120;
4738 		for (offset = 0x00a8; offset < 0x00c7; offset++) {
4739 			BWN_PHY_WRITE(mac, offset, value);
4740 			value += 0x202;
4741 		}
4742 	}
4743 	BWN_PHY_SETMASK(mac, 0x0035, 0xf0ff, 0x0700);
4744 	if (phy->rf_ver == 0x2050)
4745 		BWN_PHY_WRITE(mac, 0x0038, 0x0667);
4746 
4747 	if (phy->gmode || phy->rev >= 2) {
4748 		if (phy->rf_ver == 0x2050) {
4749 			BWN_RF_SET(mac, 0x007a, 0x0020);
4750 			BWN_RF_SET(mac, 0x0051, 0x0004);
4751 		}
4752 		BWN_WRITE_2(mac, BWN_PHY_RADIO, 0x0000);
4753 
4754 		BWN_PHY_SET(mac, 0x0802, 0x0100);
4755 		BWN_PHY_SET(mac, 0x042b, 0x2000);
4756 
4757 		BWN_PHY_WRITE(mac, 0x001c, 0x186a);
4758 
4759 		BWN_PHY_SETMASK(mac, 0x0013, 0x00ff, 0x1900);
4760 		BWN_PHY_SETMASK(mac, 0x0035, 0xffc0, 0x0064);
4761 		BWN_PHY_SETMASK(mac, 0x005d, 0xff80, 0x000a);
4762 	}
4763 
4764 	if (mac->mac_flags & BWN_MAC_FLAG_BADFRAME_PREEMP)
4765 		BWN_PHY_SET(mac, BWN_PHY_RADIO_BITFIELD, (1 << 11));
4766 
4767 	if (phy->analog == 1) {
4768 		BWN_PHY_WRITE(mac, 0x0026, 0xce00);
4769 		BWN_PHY_WRITE(mac, 0x0021, 0x3763);
4770 		BWN_PHY_WRITE(mac, 0x0022, 0x1bc3);
4771 		BWN_PHY_WRITE(mac, 0x0023, 0x06f9);
4772 		BWN_PHY_WRITE(mac, 0x0024, 0x037e);
4773 	} else
4774 		BWN_PHY_WRITE(mac, 0x0026, 0xcc00);
4775 	BWN_PHY_WRITE(mac, 0x0030, 0x00c6);
4776 	BWN_WRITE_2(mac, 0x03ec, 0x3f22);
4777 
4778 	if (phy->analog == 1)
4779 		BWN_PHY_WRITE(mac, 0x0020, 0x3e1c);
4780 	else
4781 		BWN_PHY_WRITE(mac, 0x0020, 0x301c);
4782 
4783 	if (phy->analog == 0)
4784 		BWN_WRITE_2(mac, 0x03e4, 0x3000);
4785 
4786 	old_channel = phy->chan;
4787 	bwn_phy_g_switch_chan(mac, 7, 0);
4788 
4789 	if (phy->rf_ver != 0x2050) {
4790 		BWN_RF_WRITE(mac, 0x0075, 0x0080);
4791 		BWN_RF_WRITE(mac, 0x0079, 0x0081);
4792 	}
4793 
4794 	BWN_RF_WRITE(mac, 0x0050, 0x0020);
4795 	BWN_RF_WRITE(mac, 0x0050, 0x0023);
4796 
4797 	if (phy->rf_ver == 0x2050) {
4798 		BWN_RF_WRITE(mac, 0x0050, 0x0020);
4799 		BWN_RF_WRITE(mac, 0x005a, 0x0070);
4800 	}
4801 
4802 	BWN_RF_WRITE(mac, 0x005b, 0x007b);
4803 	BWN_RF_WRITE(mac, 0x005c, 0x00b0);
4804 	BWN_RF_SET(mac, 0x007a, 0x0007);
4805 
4806 	bwn_phy_g_switch_chan(mac, old_channel, 0);
4807 	BWN_PHY_WRITE(mac, 0x0014, 0x0080);
4808 	BWN_PHY_WRITE(mac, 0x0032, 0x00ca);
4809 	BWN_PHY_WRITE(mac, 0x002a, 0x88a3);
4810 
4811 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
4812 	    pg->pg_txctl);
4813 
4814 	if (phy->rf_ver == 0x2050)
4815 		BWN_RF_WRITE(mac, 0x005d, 0x000d);
4816 
4817 	BWN_WRITE_2(mac, 0x03e4, (BWN_READ_2(mac, 0x03e4) & 0xffc0) | 0x0004);
4818 }
4819 
4820 static void
4821 bwn_loopback_calcgain(struct bwn_mac *mac)
4822 {
4823 	struct bwn_phy *phy = &mac->mac_phy;
4824 	struct bwn_phy_g *pg = &phy->phy_g;
4825 	struct bwn_softc *sc = mac->mac_sc;
4826 	uint16_t backup_phy[16] = { 0 };
4827 	uint16_t backup_radio[3];
4828 	uint16_t backup_bband;
4829 	uint16_t i, j, loop_i_max;
4830 	uint16_t trsw_rx;
4831 	uint16_t loop1_outer_done, loop1_inner_done;
4832 
4833 	backup_phy[0] = BWN_PHY_READ(mac, BWN_PHY_CRS0);
4834 	backup_phy[1] = BWN_PHY_READ(mac, BWN_PHY_CCKBBANDCFG);
4835 	backup_phy[2] = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
4836 	backup_phy[3] = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
4837 	if (phy->rev != 1) {
4838 		backup_phy[4] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
4839 		backup_phy[5] = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
4840 	}
4841 	backup_phy[6] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
4842 	backup_phy[7] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
4843 	backup_phy[8] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
4844 	backup_phy[9] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x0a));
4845 	backup_phy[10] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x03));
4846 	backup_phy[11] = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
4847 	backup_phy[12] = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
4848 	backup_phy[13] = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2b));
4849 	backup_phy[14] = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
4850 	backup_phy[15] = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
4851 	backup_bband = pg->pg_bbatt.att;
4852 	backup_radio[0] = BWN_RF_READ(mac, 0x52);
4853 	backup_radio[1] = BWN_RF_READ(mac, 0x43);
4854 	backup_radio[2] = BWN_RF_READ(mac, 0x7a);
4855 
4856 	BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x3fff);
4857 	BWN_PHY_SET(mac, BWN_PHY_CCKBBANDCFG, 0x8000);
4858 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0002);
4859 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffd);
4860 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0001);
4861 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xfffe);
4862 	if (phy->rev != 1) {
4863 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0001);
4864 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffe);
4865 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0002);
4866 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffd);
4867 	}
4868 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x000c);
4869 	BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x000c);
4870 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0030);
4871 	BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xffcf, 0x10);
4872 
4873 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0780);
4874 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
4875 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
4876 
4877 	BWN_PHY_SET(mac, BWN_PHY_CCK(0x0a), 0x2000);
4878 	if (phy->rev != 1) {
4879 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0004);
4880 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffb);
4881 	}
4882 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xff9f, 0x40);
4883 
4884 	if (phy->rf_rev == 8)
4885 		BWN_RF_WRITE(mac, 0x43, 0x000f);
4886 	else {
4887 		BWN_RF_WRITE(mac, 0x52, 0);
4888 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x9);
4889 	}
4890 	bwn_phy_g_set_bbatt(mac, 11);
4891 
4892 	if (phy->rev >= 3)
4893 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
4894 	else
4895 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
4896 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
4897 
4898 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xffc0, 0x01);
4899 	BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x2b), 0xc0ff, 0x800);
4900 
4901 	BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0100);
4902 	BWN_PHY_MASK(mac, BWN_PHY_RFOVERVAL, 0xcfff);
4903 
4904 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) {
4905 		if (phy->rev >= 7) {
4906 			BWN_PHY_SET(mac, BWN_PHY_RFOVER, 0x0800);
4907 			BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x8000);
4908 		}
4909 	}
4910 	BWN_RF_MASK(mac, 0x7a, 0x00f7);
4911 
4912 	j = 0;
4913 	loop_i_max = (phy->rf_rev == 8) ? 15 : 9;
4914 	for (i = 0; i < loop_i_max; i++) {
4915 		for (j = 0; j < 16; j++) {
4916 			BWN_RF_WRITE(mac, 0x43, i);
4917 			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff,
4918 			    (j << 8));
4919 			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
4920 			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
4921 			DELAY(20);
4922 			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
4923 				goto done0;
4924 		}
4925 	}
4926 done0:
4927 	loop1_outer_done = i;
4928 	loop1_inner_done = j;
4929 	if (j >= 8) {
4930 		BWN_PHY_SET(mac, BWN_PHY_RFOVERVAL, 0x30);
4931 		trsw_rx = 0x1b;
4932 		for (j = j - 8; j < 16; j++) {
4933 			BWN_PHY_SETMASK(mac, BWN_PHY_RFOVERVAL, 0xf0ff, j << 8);
4934 			BWN_PHY_SETMASK(mac, BWN_PHY_PGACTL, 0x0fff, 0xa000);
4935 			BWN_PHY_SET(mac, BWN_PHY_PGACTL, 0xf000);
4936 			DELAY(20);
4937 			trsw_rx -= 3;
4938 			if (BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE) >= 0xdfc)
4939 				goto done1;
4940 		}
4941 	} else
4942 		trsw_rx = 0x18;
4943 done1:
4944 
4945 	if (phy->rev != 1) {
4946 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, backup_phy[4]);
4947 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL, backup_phy[5]);
4948 	}
4949 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), backup_phy[6]);
4950 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), backup_phy[7]);
4951 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), backup_phy[8]);
4952 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x0a), backup_phy[9]);
4953 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x03), backup_phy[10]);
4954 	BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, backup_phy[11]);
4955 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, backup_phy[12]);
4956 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), backup_phy[13]);
4957 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, backup_phy[14]);
4958 
4959 	bwn_phy_g_set_bbatt(mac, backup_bband);
4960 
4961 	BWN_RF_WRITE(mac, 0x52, backup_radio[0]);
4962 	BWN_RF_WRITE(mac, 0x43, backup_radio[1]);
4963 	BWN_RF_WRITE(mac, 0x7a, backup_radio[2]);
4964 
4965 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2] | 0x0003);
4966 	DELAY(10);
4967 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, backup_phy[2]);
4968 	BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, backup_phy[3]);
4969 	BWN_PHY_WRITE(mac, BWN_PHY_CRS0, backup_phy[0]);
4970 	BWN_PHY_WRITE(mac, BWN_PHY_CCKBBANDCFG, backup_phy[1]);
4971 
4972 	pg->pg_max_lb_gain =
4973 	    ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11;
4974 	pg->pg_trsw_rx_gain = trsw_rx * 2;
4975 }
4976 
4977 static uint16_t
4978 bwn_rf_init_bcm2050(struct bwn_mac *mac)
4979 {
4980 	struct bwn_phy *phy = &mac->mac_phy;
4981 	uint32_t tmp1 = 0, tmp2 = 0;
4982 	uint16_t rcc, i, j, pgactl, cck0, cck1, cck2, cck3, rfover, rfoverval,
4983 	    analogover, analogoverval, crs0, classctl, lomask, loctl, syncctl,
4984 	    radio0, radio1, radio2, reg0, reg1, reg2, radio78, reg, index;
4985 	static const uint8_t rcc_table[] = {
4986 		0x02, 0x03, 0x01, 0x0f,
4987 		0x06, 0x07, 0x05, 0x0f,
4988 		0x0a, 0x0b, 0x09, 0x0f,
4989 		0x0e, 0x0f, 0x0d, 0x0f,
4990 	};
4991 
4992 	loctl = lomask = reg0 = classctl = crs0 = analogoverval = analogover =
4993 	    rfoverval = rfover = cck3 = 0;
4994 	radio0 = BWN_RF_READ(mac, 0x43);
4995 	radio1 = BWN_RF_READ(mac, 0x51);
4996 	radio2 = BWN_RF_READ(mac, 0x52);
4997 	pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
4998 	cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x5a));
4999 	cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x59));
5000 	cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x58));
5001 
5002 	if (phy->type == BWN_PHYTYPE_B) {
5003 		cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
5004 		reg0 = BWN_READ_2(mac, 0x3ec);
5005 
5006 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0xff);
5007 		BWN_WRITE_2(mac, 0x3ec, 0x3f3f);
5008 	} else if (phy->gmode || phy->rev >= 2) {
5009 		rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
5010 		rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
5011 		analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
5012 		analogoverval = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
5013 		crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
5014 		classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
5015 
5016 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
5017 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
5018 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
5019 		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
5020 		if (BWN_HAS_LOOPBACK(phy)) {
5021 			lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
5022 			loctl = BWN_PHY_READ(mac, BWN_PHY_LO_CTL);
5023 			if (phy->rev >= 3)
5024 				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc020);
5025 			else
5026 				BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8020);
5027 			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, 0);
5028 		}
5029 
5030 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5031 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5032 			BWN_LPD(0, 1, 1)));
5033 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER,
5034 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVER, 0));
5035 	}
5036 	BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2) | 0x8000);
5037 
5038 	syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
5039 	BWN_PHY_MASK(mac, BWN_PHY_SYNCCTL, 0xff7f);
5040 	reg1 = BWN_READ_2(mac, 0x3e6);
5041 	reg2 = BWN_READ_2(mac, 0x3f4);
5042 
5043 	if (phy->analog == 0)
5044 		BWN_WRITE_2(mac, 0x03e6, 0x0122);
5045 	else {
5046 		if (phy->analog >= 2)
5047 			BWN_PHY_SETMASK(mac, BWN_PHY_CCK(0x03), 0xffbf, 0x40);
5048 		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
5049 		    (BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000));
5050 	}
5051 
5052 	reg = BWN_RF_READ(mac, 0x60);
5053 	index = (reg & 0x001e) >> 1;
5054 	rcc = (((rcc_table[index] << 1) | (reg & 0x0001)) | 0x0020);
5055 
5056 	if (phy->type == BWN_PHYTYPE_B)
5057 		BWN_RF_WRITE(mac, 0x78, 0x26);
5058 	if (phy->gmode || phy->rev >= 2) {
5059 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5060 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5061 			BWN_LPD(0, 1, 1)));
5062 	}
5063 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfaf);
5064 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1403);
5065 	if (phy->gmode || phy->rev >= 2) {
5066 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5067 		    bwn_rf_2050_rfoverval(mac, BWN_PHY_RFOVERVAL,
5068 			BWN_LPD(0, 0, 1)));
5069 	}
5070 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xbfa0);
5071 	BWN_RF_SET(mac, 0x51, 0x0004);
5072 	if (phy->rf_rev == 8)
5073 		BWN_RF_WRITE(mac, 0x43, 0x1f);
5074 	else {
5075 		BWN_RF_WRITE(mac, 0x52, 0);
5076 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, 0x0009);
5077 	}
5078 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5079 
5080 	for (i = 0; i < 16; i++) {
5081 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0480);
5082 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5083 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5084 		if (phy->gmode || phy->rev >= 2) {
5085 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5086 			    bwn_rf_2050_rfoverval(mac,
5087 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5088 		}
5089 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5090 		DELAY(10);
5091 		if (phy->gmode || phy->rev >= 2) {
5092 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5093 			    bwn_rf_2050_rfoverval(mac,
5094 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5095 		}
5096 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5097 		DELAY(10);
5098 		if (phy->gmode || phy->rev >= 2) {
5099 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5100 			    bwn_rf_2050_rfoverval(mac,
5101 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5102 		}
5103 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5104 		DELAY(20);
5105 		tmp1 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5106 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5107 		if (phy->gmode || phy->rev >= 2) {
5108 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5109 			    bwn_rf_2050_rfoverval(mac,
5110 				BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5111 		}
5112 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5113 	}
5114 	DELAY(10);
5115 
5116 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5117 	tmp1++;
5118 	tmp1 >>= 9;
5119 
5120 	for (i = 0; i < 16; i++) {
5121 		radio78 = (BWN_BITREV4(i) << 1) | 0x0020;
5122 		BWN_RF_WRITE(mac, 0x78, radio78);
5123 		DELAY(10);
5124 		for (j = 0; j < 16; j++) {
5125 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), 0x0d80);
5126 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), 0xc810);
5127 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0x000d);
5128 			if (phy->gmode || phy->rev >= 2) {
5129 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5130 				    bwn_rf_2050_rfoverval(mac,
5131 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5132 			}
5133 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5134 			DELAY(10);
5135 			if (phy->gmode || phy->rev >= 2) {
5136 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5137 				    bwn_rf_2050_rfoverval(mac,
5138 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5139 			}
5140 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xefb0);
5141 			DELAY(10);
5142 			if (phy->gmode || phy->rev >= 2) {
5143 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5144 				    bwn_rf_2050_rfoverval(mac,
5145 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 0)));
5146 			}
5147 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xfff0);
5148 			DELAY(10);
5149 			tmp2 += BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5150 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), 0);
5151 			if (phy->gmode || phy->rev >= 2) {
5152 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL,
5153 				    bwn_rf_2050_rfoverval(mac,
5154 					BWN_PHY_RFOVERVAL, BWN_LPD(1, 0, 1)));
5155 			}
5156 			BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xafb0);
5157 		}
5158 		tmp2++;
5159 		tmp2 >>= 8;
5160 		if (tmp1 < tmp2)
5161 			break;
5162 	}
5163 
5164 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pgactl);
5165 	BWN_RF_WRITE(mac, 0x51, radio1);
5166 	BWN_RF_WRITE(mac, 0x52, radio2);
5167 	BWN_RF_WRITE(mac, 0x43, radio0);
5168 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x5a), cck0);
5169 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x59), cck1);
5170 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x58), cck2);
5171 	BWN_WRITE_2(mac, 0x3e6, reg1);
5172 	if (phy->analog != 0)
5173 		BWN_WRITE_2(mac, 0x3f4, reg2);
5174 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, syncctl);
5175 	bwn_spu_workaround(mac, phy->chan);
5176 	if (phy->type == BWN_PHYTYPE_B) {
5177 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), cck3);
5178 		BWN_WRITE_2(mac, 0x3ec, reg0);
5179 	} else if (phy->gmode) {
5180 		BWN_WRITE_2(mac, BWN_PHY_RADIO,
5181 			    BWN_READ_2(mac, BWN_PHY_RADIO)
5182 			    & 0x7fff);
5183 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, rfover);
5184 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfoverval);
5185 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, analogover);
5186 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
5187 			      analogoverval);
5188 		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, crs0);
5189 		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, classctl);
5190 		if (BWN_HAS_LOOPBACK(phy)) {
5191 			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, lomask);
5192 			BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, loctl);
5193 		}
5194 	}
5195 
5196 	return ((i > 15) ? radio78 : rcc);
5197 }
5198 
5199 static void
5200 bwn_phy_init_b6(struct bwn_mac *mac)
5201 {
5202 	struct bwn_phy *phy = &mac->mac_phy;
5203 	struct bwn_phy_g *pg = &phy->phy_g;
5204 	struct bwn_softc *sc = mac->mac_sc;
5205 	uint16_t offset, val;
5206 	uint8_t old_channel;
5207 
5208 	KASSERT(!(phy->rf_rev == 6 || phy->rf_rev == 7),
5209 	    ("%s:%d: fail", __func__, __LINE__));
5210 
5211 	BWN_PHY_WRITE(mac, 0x003e, 0x817a);
5212 	BWN_RF_WRITE(mac, 0x007a, BWN_RF_READ(mac, 0x007a) | 0x0058);
5213 	if (phy->rf_rev == 4 || phy->rf_rev == 5) {
5214 		BWN_RF_WRITE(mac, 0x51, 0x37);
5215 		BWN_RF_WRITE(mac, 0x52, 0x70);
5216 		BWN_RF_WRITE(mac, 0x53, 0xb3);
5217 		BWN_RF_WRITE(mac, 0x54, 0x9b);
5218 		BWN_RF_WRITE(mac, 0x5a, 0x88);
5219 		BWN_RF_WRITE(mac, 0x5b, 0x88);
5220 		BWN_RF_WRITE(mac, 0x5d, 0x88);
5221 		BWN_RF_WRITE(mac, 0x5e, 0x88);
5222 		BWN_RF_WRITE(mac, 0x7d, 0x88);
5223 		bwn_hf_write(mac,
5224 		    bwn_hf_read(mac) | BWN_HF_TSSI_RESET_PSM_WORKAROUN);
5225 	}
5226 	if (phy->rf_rev == 8) {
5227 		BWN_RF_WRITE(mac, 0x51, 0);
5228 		BWN_RF_WRITE(mac, 0x52, 0x40);
5229 		BWN_RF_WRITE(mac, 0x53, 0xb7);
5230 		BWN_RF_WRITE(mac, 0x54, 0x98);
5231 		BWN_RF_WRITE(mac, 0x5a, 0x88);
5232 		BWN_RF_WRITE(mac, 0x5b, 0x6b);
5233 		BWN_RF_WRITE(mac, 0x5c, 0x0f);
5234 		if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_ALTIQ) {
5235 			BWN_RF_WRITE(mac, 0x5d, 0xfa);
5236 			BWN_RF_WRITE(mac, 0x5e, 0xd8);
5237 		} else {
5238 			BWN_RF_WRITE(mac, 0x5d, 0xf5);
5239 			BWN_RF_WRITE(mac, 0x5e, 0xb8);
5240 		}
5241 		BWN_RF_WRITE(mac, 0x0073, 0x0003);
5242 		BWN_RF_WRITE(mac, 0x007d, 0x00a8);
5243 		BWN_RF_WRITE(mac, 0x007c, 0x0001);
5244 		BWN_RF_WRITE(mac, 0x007e, 0x0008);
5245 	}
5246 	for (val = 0x1e1f, offset = 0x0088; offset < 0x0098; offset++) {
5247 		BWN_PHY_WRITE(mac, offset, val);
5248 		val -= 0x0202;
5249 	}
5250 	for (val = 0x3e3f, offset = 0x0098; offset < 0x00a8; offset++) {
5251 		BWN_PHY_WRITE(mac, offset, val);
5252 		val -= 0x0202;
5253 	}
5254 	for (val = 0x2120, offset = 0x00a8; offset < 0x00c8; offset++) {
5255 		BWN_PHY_WRITE(mac, offset, (val & 0x3f3f));
5256 		val += 0x0202;
5257 	}
5258 	if (phy->type == BWN_PHYTYPE_G) {
5259 		BWN_RF_SET(mac, 0x007a, 0x0020);
5260 		BWN_RF_SET(mac, 0x0051, 0x0004);
5261 		BWN_PHY_SET(mac, 0x0802, 0x0100);
5262 		BWN_PHY_SET(mac, 0x042b, 0x2000);
5263 		BWN_PHY_WRITE(mac, 0x5b, 0);
5264 		BWN_PHY_WRITE(mac, 0x5c, 0);
5265 	}
5266 
5267 	old_channel = phy->chan;
5268 	bwn_phy_g_switch_chan(mac, (old_channel >= 8) ? 1 : 13, 0);
5269 
5270 	BWN_RF_WRITE(mac, 0x0050, 0x0020);
5271 	BWN_RF_WRITE(mac, 0x0050, 0x0023);
5272 	DELAY(40);
5273 	if (phy->rf_rev < 6 || phy->rf_rev == 8) {
5274 		BWN_RF_WRITE(mac, 0x7c, BWN_RF_READ(mac, 0x7c) | 0x0002);
5275 		BWN_RF_WRITE(mac, 0x50, 0x20);
5276 	}
5277 	if (phy->rf_rev <= 2) {
5278 		BWN_RF_WRITE(mac, 0x7c, 0x20);
5279 		BWN_RF_WRITE(mac, 0x5a, 0x70);
5280 		BWN_RF_WRITE(mac, 0x5b, 0x7b);
5281 		BWN_RF_WRITE(mac, 0x5c, 0xb0);
5282 	}
5283 	BWN_RF_SETMASK(mac, 0x007a, 0x00f8, 0x0007);
5284 
5285 	bwn_phy_g_switch_chan(mac, old_channel, 0);
5286 
5287 	BWN_PHY_WRITE(mac, 0x0014, 0x0200);
5288 	if (phy->rf_rev >= 6)
5289 		BWN_PHY_WRITE(mac, 0x2a, 0x88c2);
5290 	else
5291 		BWN_PHY_WRITE(mac, 0x2a, 0x8ac0);
5292 	BWN_PHY_WRITE(mac, 0x0038, 0x0668);
5293 	bwn_phy_g_set_txpwr_sub(mac, &pg->pg_bbatt, &pg->pg_rfatt,
5294 	    pg->pg_txctl);
5295 	if (phy->rf_rev <= 5)
5296 		BWN_PHY_SETMASK(mac, 0x5d, 0xff80, 0x0003);
5297 	if (phy->rf_rev <= 2)
5298 		BWN_RF_WRITE(mac, 0x005d, 0x000d);
5299 
5300 	if (phy->analog == 4) {
5301 		BWN_WRITE_2(mac, 0x3e4, 9);
5302 		BWN_PHY_MASK(mac, 0x61, 0x0fff);
5303 	} else
5304 		BWN_PHY_SETMASK(mac, 0x0002, 0xffc0, 0x0004);
5305 	if (phy->type == BWN_PHYTYPE_B)
5306 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5307 	else if (phy->type == BWN_PHYTYPE_G)
5308 		BWN_WRITE_2(mac, 0x03e6, 0x0);
5309 }
5310 
5311 static void
5312 bwn_phy_init_a(struct bwn_mac *mac)
5313 {
5314 	struct bwn_phy *phy = &mac->mac_phy;
5315 	struct bwn_softc *sc = mac->mac_sc;
5316 
5317 	KASSERT(phy->type == BWN_PHYTYPE_A || phy->type == BWN_PHYTYPE_G,
5318 	    ("%s:%d: fail", __func__, __LINE__));
5319 
5320 	if (phy->rev >= 6) {
5321 		if (phy->type == BWN_PHYTYPE_A)
5322 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x1000);
5323 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) & BWN_PHY_ENCORE_EN)
5324 			BWN_PHY_SET(mac, BWN_PHY_ENCORE, 0x0010);
5325 		else
5326 			BWN_PHY_MASK(mac, BWN_PHY_ENCORE, ~0x1010);
5327 	}
5328 
5329 	bwn_wa_init(mac);
5330 
5331 	if (phy->type == BWN_PHYTYPE_G &&
5332 	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_PACTRL))
5333 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x6e), 0xe000, 0x3cf);
5334 }
5335 
5336 static void
5337 bwn_wa_write_noisescale(struct bwn_mac *mac, const uint16_t *nst)
5338 {
5339 	int i;
5340 
5341 	for (i = 0; i < BWN_TAB_NOISESCALE_SIZE; i++)
5342 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_NOISESCALE, i, nst[i]);
5343 }
5344 
5345 static void
5346 bwn_wa_agc(struct bwn_mac *mac)
5347 {
5348 	struct bwn_phy *phy = &mac->mac_phy;
5349 
5350 	if (phy->rev == 1) {
5351 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 0, 254);
5352 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 1, 13);
5353 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 2, 19);
5354 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1_R1, 3, 25);
5355 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 0, 0x2710);
5356 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 1, 0x9b83);
5357 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 2, 0x9b83);
5358 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, 3, 0x0f8d);
5359 		BWN_PHY_WRITE(mac, BWN_PHY_LMS, 4);
5360 	} else {
5361 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 0, 254);
5362 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 1, 13);
5363 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 2, 19);
5364 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC1, 3, 25);
5365 	}
5366 
5367 	BWN_PHY_SETMASK(mac, BWN_PHY_CCKSHIFTBITS_WA, (uint16_t)~0xff00,
5368 	    0x5700);
5369 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x007f, 0x000f);
5370 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1a), ~0x3f80, 0x2b80);
5371 	BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, 0xf0ff, 0x0300);
5372 	BWN_RF_SET(mac, 0x7a, 0x0008);
5373 	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x000f, 0x0008);
5374 	BWN_PHY_SETMASK(mac, BWN_PHY_P1P2GAIN, ~0x0f00, 0x0600);
5375 	BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x0f00, 0x0700);
5376 	BWN_PHY_SETMASK(mac, BWN_PHY_N1P1GAIN, ~0x0f00, 0x0100);
5377 	if (phy->rev == 1)
5378 		BWN_PHY_SETMASK(mac, BWN_PHY_N1N2GAIN, ~0x000f, 0x0007);
5379 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x00ff, 0x001c);
5380 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x88), ~0x3f00, 0x0200);
5381 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), ~0x00ff, 0x001c);
5382 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x00ff, 0x0020);
5383 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x89), ~0x3f00, 0x0200);
5384 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x82), ~0x00ff, 0x002e);
5385 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x96), (uint16_t)~0xff00, 0x1a00);
5386 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), ~0x00ff, 0x0028);
5387 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x81), (uint16_t)~0xff00, 0x2c00);
5388 	if (phy->rev == 1) {
5389 		BWN_PHY_WRITE(mac, BWN_PHY_PEAK_COUNT, 0x092b);
5390 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e, 0x0002);
5391 	} else {
5392 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x1b), ~0x001e);
5393 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x1f), 0x287a);
5394 		BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL, ~0x000f, 0x0004);
5395 		if (phy->rev >= 6) {
5396 			BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x22), 0x287a);
5397 			BWN_PHY_SETMASK(mac, BWN_PHY_LPFGAINCTL,
5398 			    (uint16_t)~0xf000, 0x3000);
5399 		}
5400 	}
5401 	BWN_PHY_SETMASK(mac, BWN_PHY_DIVSRCHIDX, 0x8080, 0x7874);
5402 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8e), 0x1c00);
5403 	if (phy->rev == 1) {
5404 		BWN_PHY_SETMASK(mac, BWN_PHY_DIVP1P2GAIN, ~0x0f00, 0x0600);
5405 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8b), 0x005e);
5406 		BWN_PHY_SETMASK(mac, BWN_PHY_ANTWRSETT, ~0x00ff, 0x001e);
5407 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x8d), 0x0002);
5408 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 0, 0);
5409 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 1, 7);
5410 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 2, 16);
5411 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3_R1, 3, 28);
5412 	} else {
5413 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 0, 0);
5414 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 1, 7);
5415 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 2, 16);
5416 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC3, 3, 28);
5417 	}
5418 	if (phy->rev >= 6) {
5419 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x0003);
5420 		BWN_PHY_MASK(mac, BWN_PHY_OFDM(0x26), ~0x1000);
5421 	}
5422 	BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM);
5423 }
5424 
5425 static void
5426 bwn_wa_grev1(struct bwn_mac *mac)
5427 {
5428 	struct bwn_phy *phy = &mac->mac_phy;
5429 	int i;
5430 	static const uint16_t bwn_tab_finefreqg[] = BWN_TAB_FINEFREQ_G;
5431 	static const uint32_t bwn_tab_retard[] = BWN_TAB_RETARD;
5432 	static const uint32_t bwn_tab_rotor[] = BWN_TAB_ROTOR;
5433 
5434 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5435 
5436 	/* init CRSTHRES and ANTDWELL */
5437 	if (phy->rev == 1) {
5438 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5439 	} else if (phy->rev == 2) {
5440 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5441 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5442 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5443 	} else {
5444 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5445 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5446 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5447 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5448 	}
5449 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS0, ~0x03c0, 0xd000);
5450 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0x2c), 0x005a);
5451 	BWN_PHY_WRITE(mac, BWN_PHY_CCKSHIFTBITS, 0x0026);
5452 
5453 	/* XXX support PHY-A??? */
5454 	for (i = 0; i < N(bwn_tab_finefreqg); i++)
5455 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DACRFPABB, i,
5456 		    bwn_tab_finefreqg[i]);
5457 
5458 	/* XXX support PHY-A??? */
5459 	if (phy->rev == 1)
5460 		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5461 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5462 			    bwn_tab_noise_g1[i]);
5463 	else
5464 		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5465 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5466 			    bwn_tab_noise_g2[i]);
5467 
5468 
5469 	for (i = 0; i < N(bwn_tab_rotor); i++)
5470 		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ROTOR, i,
5471 		    bwn_tab_rotor[i]);
5472 
5473 	/* XXX support PHY-A??? */
5474 	if (phy->rev >= 6) {
5475 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5476 		    BWN_PHY_ENCORE_EN)
5477 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5478 		else
5479 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5480 	} else
5481 		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5482 
5483 	for (i = 0; i < N(bwn_tab_retard); i++)
5484 		bwn_ofdmtab_write_4(mac, BWN_OFDMTAB_ADVRETARD, i,
5485 		    bwn_tab_retard[i]);
5486 
5487 	if (phy->rev == 1) {
5488 		for (i = 0; i < 16; i++)
5489 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1,
5490 			    i, 0x0020);
5491 	} else {
5492 		for (i = 0; i < 32; i++)
5493 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5494 	}
5495 
5496 	bwn_wa_agc(mac);
5497 }
5498 
5499 static void
5500 bwn_wa_grev26789(struct bwn_mac *mac)
5501 {
5502 	struct bwn_phy *phy = &mac->mac_phy;
5503 	int i;
5504 	static const uint16_t bwn_tab_sigmasqr2[] = BWN_TAB_SIGMASQR2;
5505 	uint16_t ofdmrev;
5506 
5507 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5508 
5509 	bwn_gtab_write(mac, BWN_GTAB_ORIGTR, 0, 0xc480);
5510 
5511 	/* init CRSTHRES and ANTDWELL */
5512 	if (phy->rev == 1)
5513 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1_R1, 0x4f19);
5514 	else if (phy->rev == 2) {
5515 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x1861);
5516 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0271);
5517 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5518 	} else {
5519 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES1, 0x0098);
5520 		BWN_PHY_WRITE(mac, BWN_PHY_CRSTHRES2, 0x0070);
5521 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xc9), 0x0080);
5522 		BWN_PHY_SET(mac, BWN_PHY_ANTDWELL, 0x0800);
5523 	}
5524 
5525 	for (i = 0; i < 64; i++)
5526 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_RSSI, i, i);
5527 
5528 	/* XXX support PHY-A??? */
5529 	if (phy->rev == 1)
5530 		for (i = 0; i < N(bwn_tab_noise_g1); i++)
5531 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5532 			    bwn_tab_noise_g1[i]);
5533 	else
5534 		for (i = 0; i < N(bwn_tab_noise_g2); i++)
5535 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_AGC2, i,
5536 			    bwn_tab_noise_g2[i]);
5537 
5538 	/* XXX support PHY-A??? */
5539 	if (phy->rev >= 6) {
5540 		if (BWN_PHY_READ(mac, BWN_PHY_ENCORE) &
5541 		    BWN_PHY_ENCORE_EN)
5542 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g3);
5543 		else
5544 			bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g2);
5545 	} else
5546 		bwn_wa_write_noisescale(mac, bwn_tab_noisescale_g1);
5547 
5548 	for (i = 0; i < N(bwn_tab_sigmasqr2); i++)
5549 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_MINSIGSQ, i,
5550 		    bwn_tab_sigmasqr2[i]);
5551 
5552 	if (phy->rev == 1) {
5553 		for (i = 0; i < 16; i++)
5554 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI_R1, i,
5555 			    0x0020);
5556 	} else {
5557 		for (i = 0; i < 32; i++)
5558 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_WRSSI, i, 0x0820);
5559 	}
5560 
5561 	bwn_wa_agc(mac);
5562 
5563 	ofdmrev = BWN_PHY_READ(mac, BWN_PHY_VERSION_OFDM) & BWN_PHYVER_VERSION;
5564 	if (ofdmrev > 2) {
5565 		if (phy->type == BWN_PHYTYPE_A)
5566 			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1808);
5567 		else
5568 			BWN_PHY_WRITE(mac, BWN_PHY_PWRDOWN, 0x1000);
5569 	} else {
5570 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 3, 0x1044);
5571 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 4, 0x7201);
5572 		bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_DAC, 6, 0x0040);
5573 	}
5574 
5575 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 2, 15);
5576 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_0F, 3, 20);
5577 }
5578 
5579 static void
5580 bwn_wa_init(struct bwn_mac *mac)
5581 {
5582 	struct bwn_phy *phy = &mac->mac_phy;
5583 	struct bwn_softc *sc = mac->mac_sc;
5584 
5585 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s fail", __func__));
5586 
5587 	switch (phy->rev) {
5588 	case 1:
5589 		bwn_wa_grev1(mac);
5590 		break;
5591 	case 2:
5592 	case 6:
5593 	case 7:
5594 	case 8:
5595 	case 9:
5596 		bwn_wa_grev26789(mac);
5597 		break;
5598 	default:
5599 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
5600 	}
5601 
5602 	if (siba_get_pci_subvendor(sc->sc_dev) != SIBA_BOARDVENDOR_BCM ||
5603 	    siba_get_pci_subdevice(sc->sc_dev) != SIBA_BOARD_BU4306 ||
5604 	    siba_get_pci_revid(sc->sc_dev) != 0x17) {
5605 		if (phy->rev < 2) {
5606 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 1,
5607 			    0x0002);
5608 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX_R1, 2,
5609 			    0x0001);
5610 		} else {
5611 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 1, 0x0002);
5612 			bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX, 2, 0x0001);
5613 			if ((siba_sprom_get_bf_lo(sc->sc_dev) &
5614 			     BWN_BFL_EXTLNA) &&
5615 			    (phy->rev >= 7)) {
5616 				BWN_PHY_MASK(mac, BWN_PHY_EXTG(0x11), 0xf7ff);
5617 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5618 				    0x0020, 0x0001);
5619 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5620 				    0x0021, 0x0001);
5621 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5622 				    0x0022, 0x0001);
5623 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5624 				    0x0023, 0x0000);
5625 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5626 				    0x0000, 0x0000);
5627 				bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_GAINX,
5628 				    0x0003, 0x0002);
5629 			}
5630 		}
5631 	}
5632 	if (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) {
5633 		BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, 0x3120);
5634 		BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, 0xc480);
5635 	}
5636 
5637 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 0, 0);
5638 	bwn_ofdmtab_write_2(mac, BWN_OFDMTAB_UNKNOWN_11, 1, 0);
5639 }
5640 
5641 static void
5642 bwn_ofdmtab_write_2(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5643     uint16_t value)
5644 {
5645 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5646 	uint16_t addr;
5647 
5648 	addr = table + offset;
5649 	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5650 	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5651 		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5652 		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5653 	}
5654 	pg->pg_ofdmtab_addr = addr;
5655 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5656 }
5657 
5658 static void
5659 bwn_ofdmtab_write_4(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5660     uint32_t value)
5661 {
5662 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
5663 	uint16_t addr;
5664 
5665 	addr = table + offset;
5666 	if ((pg->pg_ofdmtab_dir != BWN_OFDMTAB_DIR_WRITE) ||
5667 	    (addr - 1 != pg->pg_ofdmtab_addr)) {
5668 		BWN_PHY_WRITE(mac, BWN_PHY_OTABLECTL, addr);
5669 		pg->pg_ofdmtab_dir = BWN_OFDMTAB_DIR_WRITE;
5670 	}
5671 	pg->pg_ofdmtab_addr = addr;
5672 
5673 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEI, value);
5674 	BWN_PHY_WRITE(mac, BWN_PHY_OTABLEQ, (value >> 16));
5675 }
5676 
5677 static void
5678 bwn_gtab_write(struct bwn_mac *mac, uint16_t table, uint16_t offset,
5679     uint16_t value)
5680 {
5681 
5682 	BWN_PHY_WRITE(mac, BWN_PHY_GTABCTL, table + offset);
5683 	BWN_PHY_WRITE(mac, BWN_PHY_GTABDATA, value);
5684 }
5685 
5686 static void
5687 bwn_dummy_transmission(struct bwn_mac *mac, int ofdm, int paon)
5688 {
5689 	struct bwn_phy *phy = &mac->mac_phy;
5690 	struct bwn_softc *sc = mac->mac_sc;
5691 	unsigned int i, max_loop;
5692 	uint16_t value;
5693 	uint32_t buffer[5] = {
5694 		0x00000000, 0x00d40000, 0x00000000, 0x01000000, 0x00000000
5695 	};
5696 
5697 	if (ofdm) {
5698 		max_loop = 0x1e;
5699 		buffer[0] = 0x000201cc;
5700 	} else {
5701 		max_loop = 0xfa;
5702 		buffer[0] = 0x000b846e;
5703 	}
5704 
5705 	BWN_ASSERT_LOCKED(mac->mac_sc);
5706 
5707 	for (i = 0; i < 5; i++)
5708 		bwn_ram_write(mac, i * 4, buffer[i]);
5709 
5710 	BWN_WRITE_2(mac, 0x0568, 0x0000);
5711 	BWN_WRITE_2(mac, 0x07c0,
5712 	    (siba_get_revid(sc->sc_dev) < 11) ? 0x0000 : 0x0100);
5713 	value = ((phy->type == BWN_PHYTYPE_A) ? 0x41 : 0x40);
5714 	BWN_WRITE_2(mac, 0x050c, value);
5715 	if (phy->type == BWN_PHYTYPE_LP)
5716 		BWN_WRITE_2(mac, 0x0514, 0x1a02);
5717 	BWN_WRITE_2(mac, 0x0508, 0x0000);
5718 	BWN_WRITE_2(mac, 0x050a, 0x0000);
5719 	BWN_WRITE_2(mac, 0x054c, 0x0000);
5720 	BWN_WRITE_2(mac, 0x056a, 0x0014);
5721 	BWN_WRITE_2(mac, 0x0568, 0x0826);
5722 	BWN_WRITE_2(mac, 0x0500, 0x0000);
5723 	if (phy->type == BWN_PHYTYPE_LP)
5724 		BWN_WRITE_2(mac, 0x0502, 0x0050);
5725 	else
5726 		BWN_WRITE_2(mac, 0x0502, 0x0030);
5727 
5728 	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5729 		BWN_RF_WRITE(mac, 0x0051, 0x0017);
5730 	for (i = 0x00; i < max_loop; i++) {
5731 		value = BWN_READ_2(mac, 0x050e);
5732 		if (value & 0x0080)
5733 			break;
5734 		DELAY(10);
5735 	}
5736 	for (i = 0x00; i < 0x0a; i++) {
5737 		value = BWN_READ_2(mac, 0x050e);
5738 		if (value & 0x0400)
5739 			break;
5740 		DELAY(10);
5741 	}
5742 	for (i = 0x00; i < 0x19; i++) {
5743 		value = BWN_READ_2(mac, 0x0690);
5744 		if (!(value & 0x0100))
5745 			break;
5746 		DELAY(10);
5747 	}
5748 	if (phy->rf_ver == 0x2050 && phy->rf_rev <= 0x5)
5749 		BWN_RF_WRITE(mac, 0x0051, 0x0037);
5750 }
5751 
5752 static void
5753 bwn_ram_write(struct bwn_mac *mac, uint16_t offset, uint32_t val)
5754 {
5755 	uint32_t macctl;
5756 
5757 	KASSERT(offset % 4 == 0, ("%s:%d: fail", __func__, __LINE__));
5758 
5759 	macctl = BWN_READ_4(mac, BWN_MACCTL);
5760 	if (macctl & BWN_MACCTL_BIGENDIAN)
5761 		printf("TODO: need swap\n");
5762 
5763 	BWN_WRITE_4(mac, BWN_RAM_CONTROL, offset);
5764 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
5765 	BWN_WRITE_4(mac, BWN_RAM_DATA, val);
5766 }
5767 
5768 static void
5769 bwn_lo_write(struct bwn_mac *mac, struct bwn_loctl *ctl)
5770 {
5771 	uint16_t value;
5772 
5773 	KASSERT(mac->mac_phy.type == BWN_PHYTYPE_G,
5774 	    ("%s:%d: fail", __func__, __LINE__));
5775 
5776 	value = (uint8_t) (ctl->q);
5777 	value |= ((uint8_t) (ctl->i)) << 8;
5778 	BWN_PHY_WRITE(mac, BWN_PHY_LO_CTL, value);
5779 }
5780 
5781 static uint16_t
5782 bwn_lo_calcfeed(struct bwn_mac *mac,
5783     uint16_t lna, uint16_t pga, uint16_t trsw_rx)
5784 {
5785 	struct bwn_phy *phy = &mac->mac_phy;
5786 	struct bwn_softc *sc = mac->mac_sc;
5787 	uint16_t rfover;
5788 	uint16_t feedthrough;
5789 
5790 	if (phy->gmode) {
5791 		lna <<= BWN_PHY_RFOVERVAL_LNA_SHIFT;
5792 		pga <<= BWN_PHY_RFOVERVAL_PGA_SHIFT;
5793 
5794 		KASSERT((lna & ~BWN_PHY_RFOVERVAL_LNA) == 0,
5795 		    ("%s:%d: fail", __func__, __LINE__));
5796 		KASSERT((pga & ~BWN_PHY_RFOVERVAL_PGA) == 0,
5797 		    ("%s:%d: fail", __func__, __LINE__));
5798 
5799 		trsw_rx &= (BWN_PHY_RFOVERVAL_TRSWRX | BWN_PHY_RFOVERVAL_BW);
5800 
5801 		rfover = BWN_PHY_RFOVERVAL_UNK | pga | lna | trsw_rx;
5802 		if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA) &&
5803 		    phy->rev > 6)
5804 			rfover |= BWN_PHY_RFOVERVAL_EXTLNA;
5805 
5806 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
5807 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5808 		DELAY(10);
5809 		rfover |= BWN_PHY_RFOVERVAL_BW_LBW;
5810 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5811 		DELAY(10);
5812 		rfover |= BWN_PHY_RFOVERVAL_BW_LPF;
5813 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, rfover);
5814 		DELAY(10);
5815 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xf300);
5816 	} else {
5817 		pga |= BWN_PHY_PGACTL_UNKNOWN;
5818 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5819 		DELAY(10);
5820 		pga |= BWN_PHY_PGACTL_LOWBANDW;
5821 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5822 		DELAY(10);
5823 		pga |= BWN_PHY_PGACTL_LPF;
5824 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, pga);
5825 	}
5826 	DELAY(21);
5827 	feedthrough = BWN_PHY_READ(mac, BWN_PHY_LO_LEAKAGE);
5828 
5829 	return (feedthrough);
5830 }
5831 
5832 static uint16_t
5833 bwn_lo_txctl_regtable(struct bwn_mac *mac,
5834     uint16_t *value, uint16_t *pad_mix_gain)
5835 {
5836 	struct bwn_phy *phy = &mac->mac_phy;
5837 	uint16_t reg, v, padmix;
5838 
5839 	if (phy->type == BWN_PHYTYPE_B) {
5840 		v = 0x30;
5841 		if (phy->rf_rev <= 5) {
5842 			reg = 0x43;
5843 			padmix = 0;
5844 		} else {
5845 			reg = 0x52;
5846 			padmix = 5;
5847 		}
5848 	} else {
5849 		if (phy->rev >= 2 && phy->rf_rev == 8) {
5850 			reg = 0x43;
5851 			v = 0x10;
5852 			padmix = 2;
5853 		} else {
5854 			reg = 0x52;
5855 			v = 0x30;
5856 			padmix = 5;
5857 		}
5858 	}
5859 	if (value)
5860 		*value = v;
5861 	if (pad_mix_gain)
5862 		*pad_mix_gain = padmix;
5863 
5864 	return (reg);
5865 }
5866 
5867 static void
5868 bwn_lo_measure_txctl_values(struct bwn_mac *mac)
5869 {
5870 	struct bwn_phy *phy = &mac->mac_phy;
5871 	struct bwn_phy_g *pg = &phy->phy_g;
5872 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5873 	uint16_t reg, mask;
5874 	uint16_t trsw_rx, pga;
5875 	uint16_t rf_pctl_reg;
5876 
5877 	static const uint8_t tx_bias_values[] = {
5878 		0x09, 0x08, 0x0a, 0x01, 0x00,
5879 		0x02, 0x05, 0x04, 0x06,
5880 	};
5881 	static const uint8_t tx_magn_values[] = {
5882 		0x70, 0x40,
5883 	};
5884 
5885 	if (!BWN_HAS_LOOPBACK(phy)) {
5886 		rf_pctl_reg = 6;
5887 		trsw_rx = 2;
5888 		pga = 0;
5889 	} else {
5890 		int lb_gain;
5891 
5892 		trsw_rx = 0;
5893 		lb_gain = pg->pg_max_lb_gain / 2;
5894 		if (lb_gain > 10) {
5895 			rf_pctl_reg = 0;
5896 			pga = abs(10 - lb_gain) / 6;
5897 			pga = MIN(MAX(pga, 0), 15);
5898 		} else {
5899 			int cmp_val;
5900 			int tmp;
5901 
5902 			pga = 0;
5903 			cmp_val = 0x24;
5904 			if ((phy->rev >= 2) &&
5905 			    (phy->rf_ver == 0x2050) && (phy->rf_rev == 8))
5906 				cmp_val = 0x3c;
5907 			tmp = lb_gain;
5908 			if ((10 - lb_gain) < cmp_val)
5909 				tmp = (10 - lb_gain);
5910 			if (tmp < 0)
5911 				tmp += 6;
5912 			else
5913 				tmp += 3;
5914 			cmp_val /= 4;
5915 			tmp /= 4;
5916 			if (tmp >= cmp_val)
5917 				rf_pctl_reg = cmp_val;
5918 			else
5919 				rf_pctl_reg = tmp;
5920 		}
5921 	}
5922 	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rf_pctl_reg);
5923 	bwn_phy_g_set_bbatt(mac, 2);
5924 
5925 	reg = bwn_lo_txctl_regtable(mac, &mask, NULL);
5926 	mask = ~mask;
5927 	BWN_RF_MASK(mac, reg, mask);
5928 
5929 	if (BWN_HAS_TXMAG(phy)) {
5930 		int i, j;
5931 		int feedthrough;
5932 		int min_feedth = 0xffff;
5933 		uint8_t tx_magn, tx_bias;
5934 
5935 		for (i = 0; i < N(tx_magn_values); i++) {
5936 			tx_magn = tx_magn_values[i];
5937 			BWN_RF_SETMASK(mac, 0x52, 0xff0f, tx_magn);
5938 			for (j = 0; j < N(tx_bias_values); j++) {
5939 				tx_bias = tx_bias_values[j];
5940 				BWN_RF_SETMASK(mac, 0x52, 0xfff0, tx_bias);
5941 				feedthrough = bwn_lo_calcfeed(mac, 0, pga,
5942 				    trsw_rx);
5943 				if (feedthrough < min_feedth) {
5944 					lo->tx_bias = tx_bias;
5945 					lo->tx_magn = tx_magn;
5946 					min_feedth = feedthrough;
5947 				}
5948 				if (lo->tx_bias == 0)
5949 					break;
5950 			}
5951 			BWN_RF_WRITE(mac, 0x52,
5952 					  (BWN_RF_READ(mac, 0x52)
5953 					   & 0xff00) | lo->tx_bias | lo->
5954 					  tx_magn);
5955 		}
5956 	} else {
5957 		lo->tx_magn = 0;
5958 		lo->tx_bias = 0;
5959 		BWN_RF_MASK(mac, 0x52, 0xfff0);
5960 	}
5961 
5962 	BWN_GETTIME(lo->txctl_measured_time);
5963 }
5964 
5965 static void
5966 bwn_lo_get_powervector(struct bwn_mac *mac)
5967 {
5968 	struct bwn_phy *phy = &mac->mac_phy;
5969 	struct bwn_phy_g *pg = &phy->phy_g;
5970 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
5971 	int i;
5972 	uint64_t tmp;
5973 	uint64_t power_vector = 0;
5974 
5975 	for (i = 0; i < 8; i += 2) {
5976 		tmp = bwn_shm_read_2(mac, BWN_SHARED, 0x310 + i);
5977 		power_vector |= (tmp << (i * 8));
5978 		bwn_shm_write_2(mac, BWN_SHARED, 0x310 + i, 0);
5979 	}
5980 	if (power_vector)
5981 		lo->power_vector = power_vector;
5982 
5983 	BWN_GETTIME(lo->pwr_vec_read_time);
5984 }
5985 
5986 static void
5987 bwn_lo_measure_gain_values(struct bwn_mac *mac, int16_t max_rx_gain,
5988     int use_trsw_rx)
5989 {
5990 	struct bwn_phy *phy = &mac->mac_phy;
5991 	struct bwn_phy_g *pg = &phy->phy_g;
5992 	uint16_t tmp;
5993 
5994 	if (max_rx_gain < 0)
5995 		max_rx_gain = 0;
5996 
5997 	if (BWN_HAS_LOOPBACK(phy)) {
5998 		int trsw_rx = 0;
5999 		int trsw_rx_gain;
6000 
6001 		if (use_trsw_rx) {
6002 			trsw_rx_gain = pg->pg_trsw_rx_gain / 2;
6003 			if (max_rx_gain >= trsw_rx_gain) {
6004 				trsw_rx_gain = max_rx_gain - trsw_rx_gain;
6005 				trsw_rx = 0x20;
6006 			}
6007 		} else
6008 			trsw_rx_gain = max_rx_gain;
6009 		if (trsw_rx_gain < 9) {
6010 			pg->pg_lna_lod_gain = 0;
6011 		} else {
6012 			pg->pg_lna_lod_gain = 1;
6013 			trsw_rx_gain -= 8;
6014 		}
6015 		trsw_rx_gain = MIN(MAX(trsw_rx_gain, 0), 0x2d);
6016 		pg->pg_pga_gain = trsw_rx_gain / 3;
6017 		if (pg->pg_pga_gain >= 5) {
6018 			pg->pg_pga_gain -= 5;
6019 			pg->pg_lna_gain = 2;
6020 		} else
6021 			pg->pg_lna_gain = 0;
6022 	} else {
6023 		pg->pg_lna_gain = 0;
6024 		pg->pg_trsw_rx_gain = 0x20;
6025 		if (max_rx_gain >= 0x14) {
6026 			pg->pg_lna_lod_gain = 1;
6027 			pg->pg_pga_gain = 2;
6028 		} else if (max_rx_gain >= 0x12) {
6029 			pg->pg_lna_lod_gain = 1;
6030 			pg->pg_pga_gain = 1;
6031 		} else if (max_rx_gain >= 0xf) {
6032 			pg->pg_lna_lod_gain = 1;
6033 			pg->pg_pga_gain = 0;
6034 		} else {
6035 			pg->pg_lna_lod_gain = 0;
6036 			pg->pg_pga_gain = 0;
6037 		}
6038 	}
6039 
6040 	tmp = BWN_RF_READ(mac, 0x7a);
6041 	if (pg->pg_lna_lod_gain == 0)
6042 		tmp &= ~0x0008;
6043 	else
6044 		tmp |= 0x0008;
6045 	BWN_RF_WRITE(mac, 0x7a, tmp);
6046 }
6047 
6048 static void
6049 bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6050 {
6051 	struct bwn_phy *phy = &mac->mac_phy;
6052 	struct bwn_phy_g *pg = &phy->phy_g;
6053 	struct bwn_softc *sc = mac->mac_sc;
6054 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6055 	struct timespec ts;
6056 	uint16_t tmp;
6057 
6058 	if (bwn_has_hwpctl(mac)) {
6059 		sav->phy_lomask = BWN_PHY_READ(mac, BWN_PHY_LO_MASK);
6060 		sav->phy_extg = BWN_PHY_READ(mac, BWN_PHY_EXTG(0x01));
6061 		sav->phy_dacctl_hwpctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6062 		sav->phy_cck4 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x14));
6063 		sav->phy_hpwr_tssictl = BWN_PHY_READ(mac, BWN_PHY_HPWR_TSSICTL);
6064 
6065 		BWN_PHY_SET(mac, BWN_PHY_HPWR_TSSICTL, 0x100);
6066 		BWN_PHY_SET(mac, BWN_PHY_EXTG(0x01), 0x40);
6067 		BWN_PHY_SET(mac, BWN_PHY_DACCTL, 0x40);
6068 		BWN_PHY_SET(mac, BWN_PHY_CCK(0x14), 0x200);
6069 	}
6070 	if (phy->type == BWN_PHYTYPE_B &&
6071 	    phy->rf_ver == 0x2050 && phy->rf_rev < 6) {
6072 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x16), 0x410);
6073 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x17), 0x820);
6074 	}
6075 	if (phy->rev >= 2) {
6076 		sav->phy_analogover = BWN_PHY_READ(mac, BWN_PHY_ANALOGOVER);
6077 		sav->phy_analogoverval =
6078 		    BWN_PHY_READ(mac, BWN_PHY_ANALOGOVERVAL);
6079 		sav->phy_rfover = BWN_PHY_READ(mac, BWN_PHY_RFOVER);
6080 		sav->phy_rfoverval = BWN_PHY_READ(mac, BWN_PHY_RFOVERVAL);
6081 		sav->phy_classctl = BWN_PHY_READ(mac, BWN_PHY_CLASSCTL);
6082 		sav->phy_cck3 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x3e));
6083 		sav->phy_crs0 = BWN_PHY_READ(mac, BWN_PHY_CRS0);
6084 
6085 		BWN_PHY_MASK(mac, BWN_PHY_CLASSCTL, 0xfffc);
6086 		BWN_PHY_MASK(mac, BWN_PHY_CRS0, 0x7fff);
6087 		BWN_PHY_SET(mac, BWN_PHY_ANALOGOVER, 0x0003);
6088 		BWN_PHY_MASK(mac, BWN_PHY_ANALOGOVERVAL, 0xfffc);
6089 		if (phy->type == BWN_PHYTYPE_G) {
6090 			if ((phy->rev >= 7) &&
6091 			    (siba_sprom_get_bf_lo(sc->sc_dev) &
6092 			     BWN_BFL_EXTLNA)) {
6093 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x933);
6094 			} else {
6095 				BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0x133);
6096 			}
6097 		} else {
6098 			BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, 0);
6099 		}
6100 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), 0);
6101 	}
6102 	sav->reg0 = BWN_READ_2(mac, 0x3f4);
6103 	sav->reg1 = BWN_READ_2(mac, 0x3e2);
6104 	sav->rf0 = BWN_RF_READ(mac, 0x43);
6105 	sav->rf1 = BWN_RF_READ(mac, 0x7a);
6106 	sav->phy_pgactl = BWN_PHY_READ(mac, BWN_PHY_PGACTL);
6107 	sav->phy_cck2 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x2a));
6108 	sav->phy_syncctl = BWN_PHY_READ(mac, BWN_PHY_SYNCCTL);
6109 	sav->phy_dacctl = BWN_PHY_READ(mac, BWN_PHY_DACCTL);
6110 
6111 	if (!BWN_HAS_TXMAG(phy)) {
6112 		sav->rf2 = BWN_RF_READ(mac, 0x52);
6113 		sav->rf2 &= 0x00f0;
6114 	}
6115 	if (phy->type == BWN_PHYTYPE_B) {
6116 		sav->phy_cck0 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x30));
6117 		sav->phy_cck1 = BWN_PHY_READ(mac, BWN_PHY_CCK(0x06));
6118 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), 0x00ff);
6119 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), 0x3f3f);
6120 	} else {
6121 		BWN_WRITE_2(mac, 0x3e2, BWN_READ_2(mac, 0x3e2)
6122 			    | 0x8000);
6123 	}
6124 	BWN_WRITE_2(mac, 0x3f4, BWN_READ_2(mac, 0x3f4)
6125 		    & 0xf000);
6126 
6127 	tmp =
6128 	    (phy->type == BWN_PHYTYPE_G) ? BWN_PHY_LO_MASK : BWN_PHY_CCK(0x2e);
6129 	BWN_PHY_WRITE(mac, tmp, 0x007f);
6130 
6131 	tmp = sav->phy_syncctl;
6132 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, tmp & 0xff7f);
6133 	tmp = sav->rf1;
6134 	BWN_RF_WRITE(mac, 0x007a, tmp & 0xfff0);
6135 
6136 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), 0x8a3);
6137 	if (phy->type == BWN_PHYTYPE_G ||
6138 	    (phy->type == BWN_PHYTYPE_B &&
6139 	     phy->rf_ver == 0x2050 && phy->rf_rev >= 6)) {
6140 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x1003);
6141 	} else
6142 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2b), 0x0802);
6143 	if (phy->rev >= 2)
6144 		bwn_dummy_transmission(mac, 0, 1);
6145 	bwn_phy_g_switch_chan(mac, 6, 0);
6146 	BWN_RF_READ(mac, 0x51);
6147 	if (phy->type == BWN_PHYTYPE_G)
6148 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
6149 
6150 	nanouptime(&ts);
6151 	if (time_before(lo->txctl_measured_time,
6152 	    (ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
6153 		bwn_lo_measure_txctl_values(mac);
6154 
6155 	if (phy->type == BWN_PHYTYPE_G && phy->rev >= 3)
6156 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0xc078);
6157 	else {
6158 		if (phy->type == BWN_PHYTYPE_B)
6159 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6160 		else
6161 			BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, 0x8078);
6162 	}
6163 }
6164 
6165 static void
6166 bwn_lo_restore(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
6167 {
6168 	struct bwn_phy *phy = &mac->mac_phy;
6169 	struct bwn_phy_g *pg = &phy->phy_g;
6170 	uint16_t tmp;
6171 
6172 	if (phy->rev >= 2) {
6173 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, 0xe300);
6174 		tmp = (pg->pg_pga_gain << 8);
6175 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa0);
6176 		DELAY(5);
6177 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa2);
6178 		DELAY(2);
6179 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, tmp | 0xa3);
6180 	} else {
6181 		tmp = (pg->pg_pga_gain | 0xefa0);
6182 		BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, tmp);
6183 	}
6184 	if (phy->type == BWN_PHYTYPE_G) {
6185 		if (phy->rev >= 3)
6186 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0xc078);
6187 		else
6188 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2e), 0x8078);
6189 		if (phy->rev >= 2)
6190 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0202);
6191 		else
6192 			BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0x0101);
6193 	}
6194 	BWN_WRITE_2(mac, 0x3f4, sav->reg0);
6195 	BWN_PHY_WRITE(mac, BWN_PHY_PGACTL, sav->phy_pgactl);
6196 	BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2a), sav->phy_cck2);
6197 	BWN_PHY_WRITE(mac, BWN_PHY_SYNCCTL, sav->phy_syncctl);
6198 	BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl);
6199 	BWN_RF_WRITE(mac, 0x43, sav->rf0);
6200 	BWN_RF_WRITE(mac, 0x7a, sav->rf1);
6201 	if (!BWN_HAS_TXMAG(phy)) {
6202 		tmp = sav->rf2;
6203 		BWN_RF_SETMASK(mac, 0x52, 0xff0f, tmp);
6204 	}
6205 	BWN_WRITE_2(mac, 0x3e2, sav->reg1);
6206 	if (phy->type == BWN_PHYTYPE_B &&
6207 	    phy->rf_ver == 0x2050 && phy->rf_rev <= 5) {
6208 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x30), sav->phy_cck0);
6209 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x06), sav->phy_cck1);
6210 	}
6211 	if (phy->rev >= 2) {
6212 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVER, sav->phy_analogover);
6213 		BWN_PHY_WRITE(mac, BWN_PHY_ANALOGOVERVAL,
6214 			      sav->phy_analogoverval);
6215 		BWN_PHY_WRITE(mac, BWN_PHY_CLASSCTL, sav->phy_classctl);
6216 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVER, sav->phy_rfover);
6217 		BWN_PHY_WRITE(mac, BWN_PHY_RFOVERVAL, sav->phy_rfoverval);
6218 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x3e), sav->phy_cck3);
6219 		BWN_PHY_WRITE(mac, BWN_PHY_CRS0, sav->phy_crs0);
6220 	}
6221 	if (bwn_has_hwpctl(mac)) {
6222 		tmp = (sav->phy_lomask & 0xbfff);
6223 		BWN_PHY_WRITE(mac, BWN_PHY_LO_MASK, tmp);
6224 		BWN_PHY_WRITE(mac, BWN_PHY_EXTG(0x01), sav->phy_extg);
6225 		BWN_PHY_WRITE(mac, BWN_PHY_DACCTL, sav->phy_dacctl_hwpctl);
6226 		BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x14), sav->phy_cck4);
6227 		BWN_PHY_WRITE(mac, BWN_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
6228 	}
6229 	bwn_phy_g_switch_chan(mac, sav->old_channel, 1);
6230 }
6231 
6232 static int
6233 bwn_lo_probe_loctl(struct bwn_mac *mac,
6234     struct bwn_loctl *probe, struct bwn_lo_g_sm *d)
6235 {
6236 	struct bwn_phy *phy = &mac->mac_phy;
6237 	struct bwn_phy_g *pg = &phy->phy_g;
6238 	struct bwn_loctl orig, test;
6239 	struct bwn_loctl prev = { -100, -100 };
6240 	static const struct bwn_loctl modifiers[] = {
6241 		{  1,  1,}, {  1,  0,}, {  1, -1,}, {  0, -1,},
6242 		{ -1, -1,}, { -1,  0,}, { -1,  1,}, {  0,  1,}
6243 	};
6244 	int begin, end, lower = 0, i;
6245 	uint16_t feedth;
6246 
6247 	if (d->curstate == 0) {
6248 		begin = 1;
6249 		end = 8;
6250 	} else if (d->curstate % 2 == 0) {
6251 		begin = d->curstate - 1;
6252 		end = d->curstate + 1;
6253 	} else {
6254 		begin = d->curstate - 2;
6255 		end = d->curstate + 2;
6256 	}
6257 	if (begin < 1)
6258 		begin += 8;
6259 	if (end > 8)
6260 		end -= 8;
6261 
6262 	memcpy(&orig, probe, sizeof(struct bwn_loctl));
6263 	i = begin;
6264 	d->curstate = i;
6265 	while (1) {
6266 		KASSERT(i >= 1 && i <= 8, ("%s:%d: fail", __func__, __LINE__));
6267 		memcpy(&test, &orig, sizeof(struct bwn_loctl));
6268 		test.i += modifiers[i - 1].i * d->multipler;
6269 		test.q += modifiers[i - 1].q * d->multipler;
6270 		if ((test.i != prev.i || test.q != prev.q) &&
6271 		    (abs(test.i) <= 16 && abs(test.q) <= 16)) {
6272 			bwn_lo_write(mac, &test);
6273 			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6274 			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6275 			if (feedth < d->feedth) {
6276 				memcpy(probe, &test,
6277 				    sizeof(struct bwn_loctl));
6278 				lower = 1;
6279 				d->feedth = feedth;
6280 				if (d->nmeasure < 2 && !BWN_HAS_LOOPBACK(phy))
6281 					break;
6282 			}
6283 		}
6284 		memcpy(&prev, &test, sizeof(prev));
6285 		if (i == end)
6286 			break;
6287 		if (i == 8)
6288 			i = 1;
6289 		else
6290 			i++;
6291 		d->curstate = i;
6292 	}
6293 
6294 	return (lower);
6295 }
6296 
6297 static void
6298 bwn_lo_probe_sm(struct bwn_mac *mac, struct bwn_loctl *loctl, int *rxgain)
6299 {
6300 	struct bwn_phy *phy = &mac->mac_phy;
6301 	struct bwn_phy_g *pg = &phy->phy_g;
6302 	struct bwn_lo_g_sm d;
6303 	struct bwn_loctl probe;
6304 	int lower, repeat, cnt = 0;
6305 	uint16_t feedth;
6306 
6307 	d.nmeasure = 0;
6308 	d.multipler = 1;
6309 	if (BWN_HAS_LOOPBACK(phy))
6310 		d.multipler = 3;
6311 
6312 	memcpy(&d.loctl, loctl, sizeof(struct bwn_loctl));
6313 	repeat = (BWN_HAS_LOOPBACK(phy)) ? 4 : 1;
6314 
6315 	do {
6316 		bwn_lo_write(mac, &d.loctl);
6317 		feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6318 		    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6319 		if (feedth < 0x258) {
6320 			if (feedth >= 0x12c)
6321 				*rxgain += 6;
6322 			else
6323 				*rxgain += 3;
6324 			feedth = bwn_lo_calcfeed(mac, pg->pg_lna_gain,
6325 			    pg->pg_pga_gain, pg->pg_trsw_rx_gain);
6326 		}
6327 		d.feedth = feedth;
6328 		d.curstate = 0;
6329 		do {
6330 			KASSERT(d.curstate >= 0 && d.curstate <= 8,
6331 			    ("%s:%d: fail", __func__, __LINE__));
6332 			memcpy(&probe, &d.loctl,
6333 			       sizeof(struct bwn_loctl));
6334 			lower = bwn_lo_probe_loctl(mac, &probe, &d);
6335 			if (!lower)
6336 				break;
6337 			if ((probe.i == d.loctl.i) && (probe.q == d.loctl.q))
6338 				break;
6339 			memcpy(&d.loctl, &probe, sizeof(struct bwn_loctl));
6340 			d.nmeasure++;
6341 		} while (d.nmeasure < 24);
6342 		memcpy(loctl, &d.loctl, sizeof(struct bwn_loctl));
6343 
6344 		if (BWN_HAS_LOOPBACK(phy)) {
6345 			if (d.feedth > 0x1194)
6346 				*rxgain -= 6;
6347 			else if (d.feedth < 0x5dc)
6348 				*rxgain += 3;
6349 			if (cnt == 0) {
6350 				if (d.feedth <= 0x5dc) {
6351 					d.multipler = 1;
6352 					cnt++;
6353 				} else
6354 					d.multipler = 2;
6355 			} else if (cnt == 2)
6356 				d.multipler = 1;
6357 		}
6358 		bwn_lo_measure_gain_values(mac, *rxgain, BWN_HAS_LOOPBACK(phy));
6359 	} while (++cnt < repeat);
6360 }
6361 
6362 static struct bwn_lo_calib *
6363 bwn_lo_calibset(struct bwn_mac *mac,
6364     const struct bwn_bbatt *bbatt, const struct bwn_rfatt *rfatt)
6365 {
6366 	struct bwn_phy *phy = &mac->mac_phy;
6367 	struct bwn_phy_g *pg = &phy->phy_g;
6368 	struct bwn_loctl loctl = { 0, 0 };
6369 	struct bwn_lo_calib *cal;
6370 	struct bwn_lo_g_value sval = { 0 };
6371 	int rxgain;
6372 	uint16_t pad, reg, value;
6373 
6374 	sval.old_channel = phy->chan;
6375 	bwn_mac_suspend(mac);
6376 	bwn_lo_save(mac, &sval);
6377 
6378 	reg = bwn_lo_txctl_regtable(mac, &value, &pad);
6379 	BWN_RF_SETMASK(mac, 0x43, 0xfff0, rfatt->att);
6380 	BWN_RF_SETMASK(mac, reg, ~value, (rfatt->padmix ? value :0));
6381 
6382 	rxgain = (rfatt->att * 2) + (bbatt->att / 2);
6383 	if (rfatt->padmix)
6384 		rxgain -= pad;
6385 	if (BWN_HAS_LOOPBACK(phy))
6386 		rxgain += pg->pg_max_lb_gain;
6387 	bwn_lo_measure_gain_values(mac, rxgain, BWN_HAS_LOOPBACK(phy));
6388 	bwn_phy_g_set_bbatt(mac, bbatt->att);
6389 	bwn_lo_probe_sm(mac, &loctl, &rxgain);
6390 
6391 	bwn_lo_restore(mac, &sval);
6392 	bwn_mac_enable(mac);
6393 
6394 	cal = malloc(sizeof(*cal), M_DEVBUF, M_NOWAIT | M_ZERO);
6395 	if (!cal) {
6396 		device_printf(mac->mac_sc->sc_dev, "out of memory\n");
6397 		return (NULL);
6398 	}
6399 	memcpy(&cal->bbatt, bbatt, sizeof(*bbatt));
6400 	memcpy(&cal->rfatt, rfatt, sizeof(*rfatt));
6401 	memcpy(&cal->ctl, &loctl, sizeof(loctl));
6402 
6403 	BWN_GETTIME(cal->calib_time);
6404 
6405 	return (cal);
6406 }
6407 
6408 static struct bwn_lo_calib *
6409 bwn_lo_get_calib(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
6410     const struct bwn_rfatt *rfatt)
6411 {
6412 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
6413 	struct bwn_lo_calib *c;
6414 
6415 	TAILQ_FOREACH(c, &lo->calib_list, list) {
6416 		if (!BWN_BBATTCMP(&c->bbatt, bbatt))
6417 			continue;
6418 		if (!BWN_RFATTCMP(&c->rfatt, rfatt))
6419 			continue;
6420 		return (c);
6421 	}
6422 
6423 	c = bwn_lo_calibset(mac, bbatt, rfatt);
6424 	if (!c)
6425 		return (NULL);
6426 	TAILQ_INSERT_TAIL(&lo->calib_list, c, list);
6427 
6428 	return (c);
6429 }
6430 
6431 static void
6432 bwn_phy_g_dc_lookup_init(struct bwn_mac *mac, uint8_t update)
6433 {
6434 	struct bwn_phy *phy = &mac->mac_phy;
6435 	struct bwn_phy_g *pg = &phy->phy_g;
6436 	struct bwn_softc *sc = mac->mac_sc;
6437 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
6438 	const struct bwn_rfatt *rfatt;
6439 	const struct bwn_bbatt *bbatt;
6440 	uint64_t pvector;
6441 	int i;
6442 	int rf_offset, bb_offset;
6443 	uint8_t changed = 0;
6444 
6445 	KASSERT(BWN_DC_LT_SIZE == 32, ("%s:%d: fail", __func__, __LINE__));
6446 	KASSERT(lo->rfatt.len * lo->bbatt.len <= 64,
6447 	    ("%s:%d: fail", __func__, __LINE__));
6448 
6449 	pvector = lo->power_vector;
6450 	if (!update && !pvector)
6451 		return;
6452 
6453 	bwn_mac_suspend(mac);
6454 
6455 	for (i = 0; i < BWN_DC_LT_SIZE * 2; i++) {
6456 		struct bwn_lo_calib *cal;
6457 		int idx;
6458 		uint16_t val;
6459 
6460 		if (!update && !(pvector & (((uint64_t)1ULL) << i)))
6461 			continue;
6462 		bb_offset = i / lo->rfatt.len;
6463 		rf_offset = i % lo->rfatt.len;
6464 		bbatt = &(lo->bbatt.array[bb_offset]);
6465 		rfatt = &(lo->rfatt.array[rf_offset]);
6466 
6467 		cal = bwn_lo_calibset(mac, bbatt, rfatt);
6468 		if (!cal) {
6469 			device_printf(sc->sc_dev, "LO: Could not "
6470 			    "calibrate DC table entry\n");
6471 			continue;
6472 		}
6473 		val = (uint8_t)(cal->ctl.q);
6474 		val |= ((uint8_t)(cal->ctl.i)) << 4;
6475 		free(cal, M_DEVBUF);
6476 
6477 		idx = i / 2;
6478 		if (i % 2)
6479 			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00ff)
6480 			    | ((val & 0x00ff) << 8);
6481 		else
6482 			lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xff00)
6483 			    | (val & 0x00ff);
6484 		changed = 1;
6485 	}
6486 	if (changed) {
6487 		for (i = 0; i < BWN_DC_LT_SIZE; i++)
6488 			BWN_PHY_WRITE(mac, 0x3a0 + i, lo->dc_lt[i]);
6489 	}
6490 	bwn_mac_enable(mac);
6491 }
6492 
6493 static void
6494 bwn_lo_fixup_rfatt(struct bwn_rfatt *rf)
6495 {
6496 
6497 	if (!rf->padmix)
6498 		return;
6499 	if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3))
6500 		rf->att = 4;
6501 }
6502 
6503 static void
6504 bwn_lo_g_adjust(struct bwn_mac *mac)
6505 {
6506 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
6507 	struct bwn_lo_calib *cal;
6508 	struct bwn_rfatt rf;
6509 
6510 	memcpy(&rf, &pg->pg_rfatt, sizeof(rf));
6511 	bwn_lo_fixup_rfatt(&rf);
6512 
6513 	cal = bwn_lo_get_calib(mac, &pg->pg_bbatt, &rf);
6514 	if (!cal)
6515 		return;
6516 	bwn_lo_write(mac, &cal->ctl);
6517 }
6518 
6519 static void
6520 bwn_lo_g_init(struct bwn_mac *mac)
6521 {
6522 
6523 	if (!bwn_has_hwpctl(mac))
6524 		return;
6525 
6526 	bwn_lo_get_powervector(mac);
6527 	bwn_phy_g_dc_lookup_init(mac, 1);
6528 }
6529 
6530 static void
6531 bwn_mac_suspend(struct bwn_mac *mac)
6532 {
6533 	struct bwn_softc *sc = mac->mac_sc;
6534 	int i;
6535 	uint32_t tmp;
6536 
6537 	KASSERT(mac->mac_suspended >= 0,
6538 	    ("%s:%d: fail", __func__, __LINE__));
6539 
6540 	if (mac->mac_suspended == 0) {
6541 		bwn_psctl(mac, BWN_PS_AWAKE);
6542 		BWN_WRITE_4(mac, BWN_MACCTL,
6543 			    BWN_READ_4(mac, BWN_MACCTL)
6544 			    & ~BWN_MACCTL_ON);
6545 		BWN_READ_4(mac, BWN_MACCTL);
6546 		for (i = 35; i; i--) {
6547 			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6548 			if (tmp & BWN_INTR_MAC_SUSPENDED)
6549 				goto out;
6550 			DELAY(10);
6551 		}
6552 		for (i = 40; i; i--) {
6553 			tmp = BWN_READ_4(mac, BWN_INTR_REASON);
6554 			if (tmp & BWN_INTR_MAC_SUSPENDED)
6555 				goto out;
6556 			DELAY(1000);
6557 		}
6558 		device_printf(sc->sc_dev, "MAC suspend failed\n");
6559 	}
6560 out:
6561 	mac->mac_suspended++;
6562 }
6563 
6564 static void
6565 bwn_mac_enable(struct bwn_mac *mac)
6566 {
6567 	struct bwn_softc *sc = mac->mac_sc;
6568 	uint16_t state;
6569 
6570 	state = bwn_shm_read_2(mac, BWN_SHARED,
6571 	    BWN_SHARED_UCODESTAT);
6572 	if (state != BWN_SHARED_UCODESTAT_SUSPEND &&
6573 	    state != BWN_SHARED_UCODESTAT_SLEEP)
6574 		device_printf(sc->sc_dev, "warn: firmware state (%d)\n", state);
6575 
6576 	mac->mac_suspended--;
6577 	KASSERT(mac->mac_suspended >= 0,
6578 	    ("%s:%d: fail", __func__, __LINE__));
6579 	if (mac->mac_suspended == 0) {
6580 		BWN_WRITE_4(mac, BWN_MACCTL,
6581 		    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_ON);
6582 		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_MAC_SUSPENDED);
6583 		BWN_READ_4(mac, BWN_MACCTL);
6584 		BWN_READ_4(mac, BWN_INTR_REASON);
6585 		bwn_psctl(mac, 0);
6586 	}
6587 }
6588 
6589 static void
6590 bwn_psctl(struct bwn_mac *mac, uint32_t flags)
6591 {
6592 	struct bwn_softc *sc = mac->mac_sc;
6593 	int i;
6594 	uint16_t ucstat;
6595 
6596 	KASSERT(!((flags & BWN_PS_ON) && (flags & BWN_PS_OFF)),
6597 	    ("%s:%d: fail", __func__, __LINE__));
6598 	KASSERT(!((flags & BWN_PS_AWAKE) && (flags & BWN_PS_ASLEEP)),
6599 	    ("%s:%d: fail", __func__, __LINE__));
6600 
6601 	/* XXX forcibly awake and hwps-off */
6602 
6603 	BWN_WRITE_4(mac, BWN_MACCTL,
6604 	    (BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_AWAKE) &
6605 	    ~BWN_MACCTL_HWPS);
6606 	BWN_READ_4(mac, BWN_MACCTL);
6607 	if (siba_get_revid(sc->sc_dev) >= 5) {
6608 		for (i = 0; i < 100; i++) {
6609 			ucstat = bwn_shm_read_2(mac, BWN_SHARED,
6610 			    BWN_SHARED_UCODESTAT);
6611 			if (ucstat != BWN_SHARED_UCODESTAT_SLEEP)
6612 				break;
6613 			DELAY(10);
6614 		}
6615 	}
6616 }
6617 
6618 static int16_t
6619 bwn_nrssi_read(struct bwn_mac *mac, uint16_t offset)
6620 {
6621 
6622 	BWN_PHY_WRITE(mac, BWN_PHY_NRSSI_CTRL, offset);
6623 	return ((int16_t)BWN_PHY_READ(mac, BWN_PHY_NRSSI_DATA));
6624 }
6625 
6626 static void
6627 bwn_nrssi_threshold(struct bwn_mac *mac)
6628 {
6629 	struct bwn_phy *phy = &mac->mac_phy;
6630 	struct bwn_phy_g *pg = &phy->phy_g;
6631 	struct bwn_softc *sc = mac->mac_sc;
6632 	int32_t a, b;
6633 	int16_t tmp16;
6634 	uint16_t tmpu16;
6635 
6636 	KASSERT(phy->type == BWN_PHYTYPE_G, ("%s: fail", __func__));
6637 
6638 	if (phy->gmode && (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_RSSI)) {
6639 		if (!pg->pg_aci_wlan_automatic && pg->pg_aci_enable) {
6640 			a = 0x13;
6641 			b = 0x12;
6642 		} else {
6643 			a = 0xe;
6644 			b = 0x11;
6645 		}
6646 
6647 		a = a * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6648 		a += (pg->pg_nrssi[0] << 6);
6649 		a += (a < 32) ? 31 : 32;
6650 		a = a >> 6;
6651 		a = MIN(MAX(a, -31), 31);
6652 
6653 		b = b * (pg->pg_nrssi[1] - pg->pg_nrssi[0]);
6654 		b += (pg->pg_nrssi[0] << 6);
6655 		if (b < 32)
6656 			b += 31;
6657 		else
6658 			b += 32;
6659 		b = b >> 6;
6660 		b = MIN(MAX(b, -31), 31);
6661 
6662 		tmpu16 = BWN_PHY_READ(mac, 0x048a) & 0xf000;
6663 		tmpu16 |= ((uint32_t)b & 0x0000003f);
6664 		tmpu16 |= (((uint32_t)a & 0x0000003f) << 6);
6665 		BWN_PHY_WRITE(mac, 0x048a, tmpu16);
6666 		return;
6667 	}
6668 
6669 	tmp16 = bwn_nrssi_read(mac, 0x20);
6670 	if (tmp16 >= 0x20)
6671 		tmp16 -= 0x40;
6672 	BWN_PHY_SETMASK(mac, 0x048a, 0xf000, (tmp16 < 3) ? 0x09eb : 0x0aed);
6673 }
6674 
6675 static void
6676 bwn_nrssi_slope_11g(struct bwn_mac *mac)
6677 {
6678 #define	SAVE_RF_MAX		3
6679 #define	SAVE_PHY_COMM_MAX	4
6680 #define	SAVE_PHY3_MAX		8
6681 	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6682 		{ 0x7a, 0x52, 0x43 };
6683 	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
6684 		{ 0x15, 0x5a, 0x59, 0x58 };
6685 	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
6686 		0x002e, 0x002f, 0x080f, BWN_PHY_G_LOCTL,
6687 		0x0801, 0x0060, 0x0014, 0x0478
6688 	};
6689 	struct bwn_phy *phy = &mac->mac_phy;
6690 	struct bwn_phy_g *pg = &phy->phy_g;
6691 	int32_t i, tmp32, phy3_idx = 0;
6692 	uint16_t delta, tmp;
6693 	uint16_t save_rf[SAVE_RF_MAX];
6694 	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6695 	uint16_t save_phy3[SAVE_PHY3_MAX];
6696 	uint16_t ant_div, phy0, chan_ex;
6697 	int16_t nrssi0, nrssi1;
6698 
6699 	KASSERT(phy->type == BWN_PHYTYPE_G,
6700 	    ("%s:%d: fail", __func__, __LINE__));
6701 
6702 	if (phy->rf_rev >= 9)
6703 		return;
6704 	if (phy->rf_rev == 8)
6705 		bwn_nrssi_offset(mac);
6706 
6707 	BWN_PHY_MASK(mac, BWN_PHY_G_CRS, 0x7fff);
6708 	BWN_PHY_MASK(mac, 0x0802, 0xfffc);
6709 
6710 	/*
6711 	 * Save RF/PHY registers for later restoration
6712 	 */
6713 	ant_div = BWN_READ_2(mac, 0x03e2);
6714 	BWN_WRITE_2(mac, 0x03e2, BWN_READ_2(mac, 0x03e2) | 0x8000);
6715 	for (i = 0; i < SAVE_RF_MAX; ++i)
6716 		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6717 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6718 		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6719 
6720 	phy0 = BWN_READ_2(mac, BWN_PHY0);
6721 	chan_ex = BWN_READ_2(mac, BWN_CHANNEL_EXT);
6722 	if (phy->rev >= 3) {
6723 		for (i = 0; i < SAVE_PHY3_MAX; ++i)
6724 			save_phy3[i] = BWN_PHY_READ(mac, save_phy3_regs[i]);
6725 		BWN_PHY_WRITE(mac, 0x002e, 0);
6726 		BWN_PHY_WRITE(mac, BWN_PHY_G_LOCTL, 0);
6727 		switch (phy->rev) {
6728 		case 4:
6729 		case 6:
6730 		case 7:
6731 			BWN_PHY_SET(mac, 0x0478, 0x0100);
6732 			BWN_PHY_SET(mac, 0x0801, 0x0040);
6733 			break;
6734 		case 3:
6735 		case 5:
6736 			BWN_PHY_MASK(mac, 0x0801, 0xffbf);
6737 			break;
6738 		}
6739 		BWN_PHY_SET(mac, 0x0060, 0x0040);
6740 		BWN_PHY_SET(mac, 0x0014, 0x0200);
6741 	}
6742 	/*
6743 	 * Calculate nrssi0
6744 	 */
6745 	BWN_RF_SET(mac, 0x007a, 0x0070);
6746 	bwn_set_all_gains(mac, 0, 8, 0);
6747 	BWN_RF_MASK(mac, 0x007a, 0x00f7);
6748 	if (phy->rev >= 2) {
6749 		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0030);
6750 		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0010);
6751 	}
6752 	BWN_RF_SET(mac, 0x007a, 0x0080);
6753 	DELAY(20);
6754 
6755 	nrssi0 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6756 	if (nrssi0 >= 0x0020)
6757 		nrssi0 -= 0x0040;
6758 
6759 	/*
6760 	 * Calculate nrssi1
6761 	 */
6762 	BWN_RF_MASK(mac, 0x007a, 0x007f);
6763 	if (phy->rev >= 2)
6764 		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6765 
6766 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
6767 	    BWN_READ_2(mac, BWN_CHANNEL_EXT) | 0x2000);
6768 	BWN_RF_SET(mac, 0x007a, 0x000f);
6769 	BWN_PHY_WRITE(mac, 0x0015, 0xf330);
6770 	if (phy->rev >= 2) {
6771 		BWN_PHY_SETMASK(mac, 0x0812, 0xffcf, 0x0020);
6772 		BWN_PHY_SETMASK(mac, 0x0811, 0xffcf, 0x0020);
6773 	}
6774 
6775 	bwn_set_all_gains(mac, 3, 0, 1);
6776 	if (phy->rf_rev == 8) {
6777 		BWN_RF_WRITE(mac, 0x0043, 0x001f);
6778 	} else {
6779 		tmp = BWN_RF_READ(mac, 0x0052) & 0xff0f;
6780 		BWN_RF_WRITE(mac, 0x0052, tmp | 0x0060);
6781 		tmp = BWN_RF_READ(mac, 0x0043) & 0xfff0;
6782 		BWN_RF_WRITE(mac, 0x0043, tmp | 0x0009);
6783 	}
6784 	BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6785 	BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6786 	BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6787 	DELAY(20);
6788 	nrssi1 = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6789 
6790 	/*
6791 	 * Install calculated narrow RSSI values
6792 	 */
6793 	if (nrssi1 >= 0x0020)
6794 		nrssi1 -= 0x0040;
6795 	if (nrssi0 == nrssi1)
6796 		pg->pg_nrssi_slope = 0x00010000;
6797 	else
6798 		pg->pg_nrssi_slope = 0x00400000 / (nrssi0 - nrssi1);
6799 	if (nrssi0 >= -4) {
6800 		pg->pg_nrssi[0] = nrssi1;
6801 		pg->pg_nrssi[1] = nrssi0;
6802 	}
6803 
6804 	/*
6805 	 * Restore saved RF/PHY registers
6806 	 */
6807 	if (phy->rev >= 3) {
6808 		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
6809 			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6810 			    save_phy3[phy3_idx]);
6811 		}
6812 	}
6813 	if (phy->rev >= 2) {
6814 		BWN_PHY_MASK(mac, 0x0812, 0xffcf);
6815 		BWN_PHY_MASK(mac, 0x0811, 0xffcf);
6816 	}
6817 
6818 	for (i = 0; i < SAVE_RF_MAX; ++i)
6819 		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6820 
6821 	BWN_WRITE_2(mac, 0x03e2, ant_div);
6822 	BWN_WRITE_2(mac, 0x03e6, phy0);
6823 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT, chan_ex);
6824 
6825 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6826 		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6827 
6828 	bwn_spu_workaround(mac, phy->chan);
6829 	BWN_PHY_SET(mac, 0x0802, (0x0001 | 0x0002));
6830 	bwn_set_original_gains(mac);
6831 	BWN_PHY_SET(mac, BWN_PHY_G_CRS, 0x8000);
6832 	if (phy->rev >= 3) {
6833 		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
6834 			BWN_PHY_WRITE(mac, save_phy3_regs[phy3_idx],
6835 			    save_phy3[phy3_idx]);
6836 		}
6837 	}
6838 
6839 	delta = 0x1f - pg->pg_nrssi[0];
6840 	for (i = 0; i < 64; i++) {
6841 		tmp32 = (((i - delta) * pg->pg_nrssi_slope) / 0x10000) + 0x3a;
6842 		tmp32 = MIN(MAX(tmp32, 0), 0x3f);
6843 		pg->pg_nrssi_lt[i] = tmp32;
6844 	}
6845 
6846 	bwn_nrssi_threshold(mac);
6847 #undef SAVE_RF_MAX
6848 #undef SAVE_PHY_COMM_MAX
6849 #undef SAVE_PHY3_MAX
6850 }
6851 
6852 static void
6853 bwn_nrssi_offset(struct bwn_mac *mac)
6854 {
6855 #define	SAVE_RF_MAX		2
6856 #define	SAVE_PHY_COMM_MAX	10
6857 #define	SAVE_PHY6_MAX		8
6858 	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
6859 		{ 0x7a, 0x43 };
6860 	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
6861 		0x0001, 0x0811, 0x0812, 0x0814,
6862 		0x0815, 0x005a, 0x0059, 0x0058,
6863 		0x000a, 0x0003
6864 	};
6865 	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
6866 		0x002e, 0x002f, 0x080f, 0x0810,
6867 		0x0801, 0x0060, 0x0014, 0x0478
6868 	};
6869 	struct bwn_phy *phy = &mac->mac_phy;
6870 	int i, phy6_idx = 0;
6871 	uint16_t save_rf[SAVE_RF_MAX];
6872 	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
6873 	uint16_t save_phy6[SAVE_PHY6_MAX];
6874 	int16_t nrssi;
6875 	uint16_t saved = 0xffff;
6876 
6877 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
6878 		save_phy_comm[i] = BWN_PHY_READ(mac, save_phy_comm_regs[i]);
6879 	for (i = 0; i < SAVE_RF_MAX; ++i)
6880 		save_rf[i] = BWN_RF_READ(mac, save_rf_regs[i]);
6881 
6882 	BWN_PHY_MASK(mac, 0x0429, 0x7fff);
6883 	BWN_PHY_SETMASK(mac, 0x0001, 0x3fff, 0x4000);
6884 	BWN_PHY_SET(mac, 0x0811, 0x000c);
6885 	BWN_PHY_SETMASK(mac, 0x0812, 0xfff3, 0x0004);
6886 	BWN_PHY_MASK(mac, 0x0802, ~(0x1 | 0x2));
6887 	if (phy->rev >= 6) {
6888 		for (i = 0; i < SAVE_PHY6_MAX; ++i)
6889 			save_phy6[i] = BWN_PHY_READ(mac, save_phy6_regs[i]);
6890 
6891 		BWN_PHY_WRITE(mac, 0x002e, 0);
6892 		BWN_PHY_WRITE(mac, 0x002f, 0);
6893 		BWN_PHY_WRITE(mac, 0x080f, 0);
6894 		BWN_PHY_WRITE(mac, 0x0810, 0);
6895 		BWN_PHY_SET(mac, 0x0478, 0x0100);
6896 		BWN_PHY_SET(mac, 0x0801, 0x0040);
6897 		BWN_PHY_SET(mac, 0x0060, 0x0040);
6898 		BWN_PHY_SET(mac, 0x0014, 0x0200);
6899 	}
6900 	BWN_RF_SET(mac, 0x007a, 0x0070);
6901 	BWN_RF_SET(mac, 0x007a, 0x0080);
6902 	DELAY(30);
6903 
6904 	nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6905 	if (nrssi >= 0x20)
6906 		nrssi -= 0x40;
6907 	if (nrssi == 31) {
6908 		for (i = 7; i >= 4; i--) {
6909 			BWN_RF_WRITE(mac, 0x007b, i);
6910 			DELAY(20);
6911 			nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) &
6912 			    0x003f);
6913 			if (nrssi >= 0x20)
6914 				nrssi -= 0x40;
6915 			if (nrssi < 31 && saved == 0xffff)
6916 				saved = i;
6917 		}
6918 		if (saved == 0xffff)
6919 			saved = 4;
6920 	} else {
6921 		BWN_RF_MASK(mac, 0x007a, 0x007f);
6922 		if (phy->rev != 1) {
6923 			BWN_PHY_SET(mac, 0x0814, 0x0001);
6924 			BWN_PHY_MASK(mac, 0x0815, 0xfffe);
6925 		}
6926 		BWN_PHY_SET(mac, 0x0811, 0x000c);
6927 		BWN_PHY_SET(mac, 0x0812, 0x000c);
6928 		BWN_PHY_SET(mac, 0x0811, 0x0030);
6929 		BWN_PHY_SET(mac, 0x0812, 0x0030);
6930 		BWN_PHY_WRITE(mac, 0x005a, 0x0480);
6931 		BWN_PHY_WRITE(mac, 0x0059, 0x0810);
6932 		BWN_PHY_WRITE(mac, 0x0058, 0x000d);
6933 		if (phy->rev == 0)
6934 			BWN_PHY_WRITE(mac, 0x0003, 0x0122);
6935 		else
6936 			BWN_PHY_SET(mac, 0x000a, 0x2000);
6937 		if (phy->rev != 1) {
6938 			BWN_PHY_SET(mac, 0x0814, 0x0004);
6939 			BWN_PHY_MASK(mac, 0x0815, 0xfffb);
6940 		}
6941 		BWN_PHY_SETMASK(mac, 0x0003, 0xff9f, 0x0040);
6942 		BWN_RF_SET(mac, 0x007a, 0x000f);
6943 		bwn_set_all_gains(mac, 3, 0, 1);
6944 		BWN_RF_SETMASK(mac, 0x0043, 0x00f0, 0x000f);
6945 		DELAY(30);
6946 		nrssi = (int16_t) ((BWN_PHY_READ(mac, 0x047f) >> 8) & 0x003f);
6947 		if (nrssi >= 0x20)
6948 			nrssi -= 0x40;
6949 		if (nrssi == -32) {
6950 			for (i = 0; i < 4; i++) {
6951 				BWN_RF_WRITE(mac, 0x007b, i);
6952 				DELAY(20);
6953 				nrssi = (int16_t)((BWN_PHY_READ(mac,
6954 				    0x047f) >> 8) & 0x003f);
6955 				if (nrssi >= 0x20)
6956 					nrssi -= 0x40;
6957 				if (nrssi > -31 && saved == 0xffff)
6958 					saved = i;
6959 			}
6960 			if (saved == 0xffff)
6961 				saved = 3;
6962 		} else
6963 			saved = 0;
6964 	}
6965 	BWN_RF_WRITE(mac, 0x007b, saved);
6966 
6967 	/*
6968 	 * Restore saved RF/PHY registers
6969 	 */
6970 	if (phy->rev >= 6) {
6971 		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
6972 			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
6973 			    save_phy6[phy6_idx]);
6974 		}
6975 	}
6976 	if (phy->rev != 1) {
6977 		for (i = 3; i < 5; i++)
6978 			BWN_PHY_WRITE(mac, save_phy_comm_regs[i],
6979 			    save_phy_comm[i]);
6980 	}
6981 	for (i = 5; i < SAVE_PHY_COMM_MAX; i++)
6982 		BWN_PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
6983 
6984 	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
6985 		BWN_RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
6986 
6987 	BWN_PHY_WRITE(mac, 0x0802, BWN_PHY_READ(mac, 0x0802) | 0x1 | 0x2);
6988 	BWN_PHY_SET(mac, 0x0429, 0x8000);
6989 	bwn_set_original_gains(mac);
6990 	if (phy->rev >= 6) {
6991 		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
6992 			BWN_PHY_WRITE(mac, save_phy6_regs[phy6_idx],
6993 			    save_phy6[phy6_idx]);
6994 		}
6995 	}
6996 
6997 	BWN_PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
6998 	BWN_PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
6999 	BWN_PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
7000 }
7001 
7002 static void
7003 bwn_set_all_gains(struct bwn_mac *mac, int16_t first, int16_t second,
7004     int16_t third)
7005 {
7006 	struct bwn_phy *phy = &mac->mac_phy;
7007 	uint16_t i;
7008 	uint16_t start = 0x08, end = 0x18;
7009 	uint16_t tmp;
7010 	uint16_t table;
7011 
7012 	if (phy->rev <= 1) {
7013 		start = 0x10;
7014 		end = 0x20;
7015 	}
7016 
7017 	table = BWN_OFDMTAB_GAINX;
7018 	if (phy->rev <= 1)
7019 		table = BWN_OFDMTAB_GAINX_R1;
7020 	for (i = 0; i < 4; i++)
7021 		bwn_ofdmtab_write_2(mac, table, i, first);
7022 
7023 	for (i = start; i < end; i++)
7024 		bwn_ofdmtab_write_2(mac, table, i, second);
7025 
7026 	if (third != -1) {
7027 		tmp = ((uint16_t) third << 14) | ((uint16_t) third << 6);
7028 		BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, tmp);
7029 		BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, tmp);
7030 		BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, tmp);
7031 	}
7032 	bwn_dummy_transmission(mac, 0, 1);
7033 }
7034 
7035 static void
7036 bwn_set_original_gains(struct bwn_mac *mac)
7037 {
7038 	struct bwn_phy *phy = &mac->mac_phy;
7039 	uint16_t i, tmp;
7040 	uint16_t table;
7041 	uint16_t start = 0x0008, end = 0x0018;
7042 
7043 	if (phy->rev <= 1) {
7044 		start = 0x0010;
7045 		end = 0x0020;
7046 	}
7047 
7048 	table = BWN_OFDMTAB_GAINX;
7049 	if (phy->rev <= 1)
7050 		table = BWN_OFDMTAB_GAINX_R1;
7051 	for (i = 0; i < 4; i++) {
7052 		tmp = (i & 0xfffc);
7053 		tmp |= (i & 0x0001) << 1;
7054 		tmp |= (i & 0x0002) >> 1;
7055 
7056 		bwn_ofdmtab_write_2(mac, table, i, tmp);
7057 	}
7058 
7059 	for (i = start; i < end; i++)
7060 		bwn_ofdmtab_write_2(mac, table, i, i - start);
7061 
7062 	BWN_PHY_SETMASK(mac, 0x04a0, 0xbfbf, 0x4040);
7063 	BWN_PHY_SETMASK(mac, 0x04a1, 0xbfbf, 0x4040);
7064 	BWN_PHY_SETMASK(mac, 0x04a2, 0xbfbf, 0x4000);
7065 	bwn_dummy_transmission(mac, 0, 1);
7066 }
7067 
7068 static void
7069 bwn_phy_hwpctl_init(struct bwn_mac *mac)
7070 {
7071 	struct bwn_phy *phy = &mac->mac_phy;
7072 	struct bwn_phy_g *pg = &phy->phy_g;
7073 	struct bwn_rfatt old_rfatt, rfatt;
7074 	struct bwn_bbatt old_bbatt, bbatt;
7075 	struct bwn_softc *sc = mac->mac_sc;
7076 	uint8_t old_txctl = 0;
7077 
7078 	KASSERT(phy->type == BWN_PHYTYPE_G,
7079 	    ("%s:%d: fail", __func__, __LINE__));
7080 
7081 	if ((siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM) &&
7082 	    (siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306))
7083 		return;
7084 
7085 	BWN_PHY_WRITE(mac, 0x0028, 0x8018);
7086 
7087 	BWN_WRITE_2(mac, BWN_PHY0, BWN_READ_2(mac, BWN_PHY0) & 0xffdf);
7088 
7089 	if (!phy->gmode)
7090 		return;
7091 	bwn_hwpctl_early_init(mac);
7092 	if (pg->pg_curtssi == 0) {
7093 		if (phy->rf_ver == 0x2050 && phy->analog == 0) {
7094 			BWN_RF_SETMASK(mac, 0x0076, 0x00f7, 0x0084);
7095 		} else {
7096 			memcpy(&old_rfatt, &pg->pg_rfatt, sizeof(old_rfatt));
7097 			memcpy(&old_bbatt, &pg->pg_bbatt, sizeof(old_bbatt));
7098 			old_txctl = pg->pg_txctl;
7099 
7100 			bbatt.att = 11;
7101 			if (phy->rf_rev == 8) {
7102 				rfatt.att = 15;
7103 				rfatt.padmix = 1;
7104 			} else {
7105 				rfatt.att = 9;
7106 				rfatt.padmix = 0;
7107 			}
7108 			bwn_phy_g_set_txpwr_sub(mac, &bbatt, &rfatt, 0);
7109 		}
7110 		bwn_dummy_transmission(mac, 0, 1);
7111 		pg->pg_curtssi = BWN_PHY_READ(mac, BWN_PHY_TSSI);
7112 		if (phy->rf_ver == 0x2050 && phy->analog == 0)
7113 			BWN_RF_MASK(mac, 0x0076, 0xff7b);
7114 		else
7115 			bwn_phy_g_set_txpwr_sub(mac, &old_bbatt,
7116 			    &old_rfatt, old_txctl);
7117 	}
7118 	bwn_hwpctl_init_gphy(mac);
7119 
7120 	/* clear TSSI */
7121 	bwn_shm_write_2(mac, BWN_SHARED, 0x0058, 0x7f7f);
7122 	bwn_shm_write_2(mac, BWN_SHARED, 0x005a, 0x7f7f);
7123 	bwn_shm_write_2(mac, BWN_SHARED, 0x0070, 0x7f7f);
7124 	bwn_shm_write_2(mac, BWN_SHARED, 0x0072, 0x7f7f);
7125 }
7126 
7127 static void
7128 bwn_hwpctl_early_init(struct bwn_mac *mac)
7129 {
7130 	struct bwn_phy *phy = &mac->mac_phy;
7131 
7132 	if (!bwn_has_hwpctl(mac)) {
7133 		BWN_PHY_WRITE(mac, 0x047a, 0xc111);
7134 		return;
7135 	}
7136 
7137 	BWN_PHY_MASK(mac, 0x0036, 0xfeff);
7138 	BWN_PHY_WRITE(mac, 0x002f, 0x0202);
7139 	BWN_PHY_SET(mac, 0x047c, 0x0002);
7140 	BWN_PHY_SET(mac, 0x047a, 0xf000);
7141 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8) {
7142 		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7143 		BWN_PHY_SET(mac, 0x005d, 0x8000);
7144 		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7145 		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7146 		BWN_PHY_SET(mac, 0x0036, 0x0400);
7147 	} else {
7148 		BWN_PHY_SET(mac, 0x0036, 0x0200);
7149 		BWN_PHY_SET(mac, 0x0036, 0x0400);
7150 		BWN_PHY_MASK(mac, 0x005d, 0x7fff);
7151 		BWN_PHY_MASK(mac, 0x004f, 0xfffe);
7152 		BWN_PHY_SETMASK(mac, 0x004e, 0xffc0, 0x0010);
7153 		BWN_PHY_WRITE(mac, 0x002e, 0xc07f);
7154 		BWN_PHY_SETMASK(mac, 0x047a, 0xff0f, 0x0010);
7155 	}
7156 }
7157 
7158 static void
7159 bwn_hwpctl_init_gphy(struct bwn_mac *mac)
7160 {
7161 	struct bwn_phy *phy = &mac->mac_phy;
7162 	struct bwn_phy_g *pg = &phy->phy_g;
7163 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7164 	int i;
7165 	uint16_t nr_written = 0, tmp, value;
7166 	uint8_t rf, bb;
7167 
7168 	if (!bwn_has_hwpctl(mac)) {
7169 		bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_HW_POWERCTL);
7170 		return;
7171 	}
7172 
7173 	BWN_PHY_SETMASK(mac, 0x0036, 0xffc0,
7174 	    (pg->pg_idletssi - pg->pg_curtssi));
7175 	BWN_PHY_SETMASK(mac, 0x0478, 0xff00,
7176 	    (pg->pg_idletssi - pg->pg_curtssi));
7177 
7178 	for (i = 0; i < 32; i++)
7179 		bwn_ofdmtab_write_2(mac, 0x3c20, i, pg->pg_tssi2dbm[i]);
7180 	for (i = 32; i < 64; i++)
7181 		bwn_ofdmtab_write_2(mac, 0x3c00, i - 32, pg->pg_tssi2dbm[i]);
7182 	for (i = 0; i < 64; i += 2) {
7183 		value = (uint16_t) pg->pg_tssi2dbm[i];
7184 		value |= ((uint16_t) pg->pg_tssi2dbm[i + 1]) << 8;
7185 		BWN_PHY_WRITE(mac, 0x380 + (i / 2), value);
7186 	}
7187 
7188 	for (rf = 0; rf < lo->rfatt.len; rf++) {
7189 		for (bb = 0; bb < lo->bbatt.len; bb++) {
7190 			if (nr_written >= 0x40)
7191 				return;
7192 			tmp = lo->bbatt.array[bb].att;
7193 			tmp <<= 8;
7194 			if (phy->rf_rev == 8)
7195 				tmp |= 0x50;
7196 			else
7197 				tmp |= 0x40;
7198 			tmp |= lo->rfatt.array[rf].att;
7199 			BWN_PHY_WRITE(mac, 0x3c0 + nr_written, tmp);
7200 			nr_written++;
7201 		}
7202 	}
7203 
7204 	BWN_PHY_MASK(mac, 0x0060, 0xffbf);
7205 	BWN_PHY_WRITE(mac, 0x0014, 0x0000);
7206 
7207 	KASSERT(phy->rev >= 6, ("%s:%d: fail", __func__, __LINE__));
7208 	BWN_PHY_SET(mac, 0x0478, 0x0800);
7209 	BWN_PHY_MASK(mac, 0x0478, 0xfeff);
7210 	BWN_PHY_MASK(mac, 0x0801, 0xffbf);
7211 
7212 	bwn_phy_g_dc_lookup_init(mac, 1);
7213 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_HW_POWERCTL);
7214 }
7215 
7216 static void
7217 bwn_phy_g_switch_chan(struct bwn_mac *mac, int channel, uint8_t spu)
7218 {
7219 	struct bwn_softc *sc = mac->mac_sc;
7220 
7221 	if (spu != 0)
7222 		bwn_spu_workaround(mac, channel);
7223 
7224 	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7225 
7226 	if (channel == 14) {
7227 		if (siba_sprom_get_ccode(sc->sc_dev) == SIBA_CCODE_JAPAN)
7228 			bwn_hf_write(mac,
7229 			    bwn_hf_read(mac) & ~BWN_HF_JAPAN_CHAN14_OFF);
7230 		else
7231 			bwn_hf_write(mac,
7232 			    bwn_hf_read(mac) | BWN_HF_JAPAN_CHAN14_OFF);
7233 		BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7234 		    BWN_READ_2(mac, BWN_CHANNEL_EXT) | (1 << 11));
7235 		return;
7236 	}
7237 
7238 	BWN_WRITE_2(mac, BWN_CHANNEL_EXT,
7239 	    BWN_READ_2(mac, BWN_CHANNEL_EXT) & 0xf7bf);
7240 }
7241 
7242 static uint16_t
7243 bwn_phy_g_chan2freq(uint8_t channel)
7244 {
7245 	static const uint8_t bwn_phy_g_rf_channels[] = BWN_PHY_G_RF_CHANNELS;
7246 
7247 	KASSERT(channel >= 1 && channel <= 14,
7248 	    ("%s:%d: fail", __func__, __LINE__));
7249 
7250 	return (bwn_phy_g_rf_channels[channel - 1]);
7251 }
7252 
7253 static void
7254 bwn_phy_g_set_txpwr_sub(struct bwn_mac *mac, const struct bwn_bbatt *bbatt,
7255     const struct bwn_rfatt *rfatt, uint8_t txctl)
7256 {
7257 	struct bwn_phy *phy = &mac->mac_phy;
7258 	struct bwn_phy_g *pg = &phy->phy_g;
7259 	struct bwn_txpwr_loctl *lo = &pg->pg_loctl;
7260 	uint16_t bb, rf;
7261 	uint16_t tx_bias, tx_magn;
7262 
7263 	bb = bbatt->att;
7264 	rf = rfatt->att;
7265 	tx_bias = lo->tx_bias;
7266 	tx_magn = lo->tx_magn;
7267 	if (tx_bias == 0xff)
7268 		tx_bias = 0;
7269 
7270 	pg->pg_txctl = txctl;
7271 	memmove(&pg->pg_rfatt, rfatt, sizeof(*rfatt));
7272 	pg->pg_rfatt.padmix = (txctl & BWN_TXCTL_TXMIX) ? 1 : 0;
7273 	memmove(&pg->pg_bbatt, bbatt, sizeof(*bbatt));
7274 	bwn_phy_g_set_bbatt(mac, bb);
7275 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_RADIO_ATT, rf);
7276 	if (phy->rf_ver == 0x2050 && phy->rf_rev == 8)
7277 		BWN_RF_WRITE(mac, 0x43, (rf & 0x000f) | (txctl & 0x0070));
7278 	else {
7279 		BWN_RF_SETMASK(mac, 0x43, 0xfff0, (rf & 0x000f));
7280 		BWN_RF_SETMASK(mac, 0x52, ~0x0070, (txctl & 0x0070));
7281 	}
7282 	if (BWN_HAS_TXMAG(phy))
7283 		BWN_RF_WRITE(mac, 0x52, tx_magn | tx_bias);
7284 	else
7285 		BWN_RF_SETMASK(mac, 0x52, 0xfff0, (tx_bias & 0x000f));
7286 	bwn_lo_g_adjust(mac);
7287 }
7288 
7289 static void
7290 bwn_phy_g_set_bbatt(struct bwn_mac *mac,
7291     uint16_t bbatt)
7292 {
7293 	struct bwn_phy *phy = &mac->mac_phy;
7294 
7295 	if (phy->analog == 0) {
7296 		BWN_WRITE_2(mac, BWN_PHY0,
7297 		    (BWN_READ_2(mac, BWN_PHY0) & 0xfff0) | bbatt);
7298 		return;
7299 	}
7300 	if (phy->analog > 1) {
7301 		BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xffc3, bbatt << 2);
7302 		return;
7303 	}
7304 	BWN_PHY_SETMASK(mac, BWN_PHY_DACCTL, 0xff87, bbatt << 3);
7305 }
7306 
7307 static uint16_t
7308 bwn_rf_2050_rfoverval(struct bwn_mac *mac, uint16_t reg, uint32_t lpd)
7309 {
7310 	struct bwn_phy *phy = &mac->mac_phy;
7311 	struct bwn_phy_g *pg = &phy->phy_g;
7312 	struct bwn_softc *sc = mac->mac_sc;
7313 	int max_lb_gain;
7314 	uint16_t extlna;
7315 	uint16_t i;
7316 
7317 	if (phy->gmode == 0)
7318 		return (0);
7319 
7320 	if (BWN_HAS_LOOPBACK(phy)) {
7321 		max_lb_gain = pg->pg_max_lb_gain;
7322 		max_lb_gain += (phy->rf_rev == 8) ? 0x3e : 0x26;
7323 		if (max_lb_gain >= 0x46) {
7324 			extlna = 0x3000;
7325 			max_lb_gain -= 0x46;
7326 		} else if (max_lb_gain >= 0x3a) {
7327 			extlna = 0x1000;
7328 			max_lb_gain -= 0x3a;
7329 		} else if (max_lb_gain >= 0x2e) {
7330 			extlna = 0x2000;
7331 			max_lb_gain -= 0x2e;
7332 		} else {
7333 			extlna = 0;
7334 			max_lb_gain -= 0x10;
7335 		}
7336 
7337 		for (i = 0; i < 16; i++) {
7338 			max_lb_gain -= (i * 6);
7339 			if (max_lb_gain < 6)
7340 				break;
7341 		}
7342 
7343 		if ((phy->rev < 7) ||
7344 		    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7345 			if (reg == BWN_PHY_RFOVER) {
7346 				return (0x1b3);
7347 			} else if (reg == BWN_PHY_RFOVERVAL) {
7348 				extlna |= (i << 8);
7349 				switch (lpd) {
7350 				case BWN_LPD(0, 1, 1):
7351 					return (0x0f92);
7352 				case BWN_LPD(0, 0, 1):
7353 				case BWN_LPD(1, 0, 1):
7354 					return (0x0092 | extlna);
7355 				case BWN_LPD(1, 0, 0):
7356 					return (0x0093 | extlna);
7357 				}
7358 				KASSERT(0 == 1,
7359 				    ("%s:%d: fail", __func__, __LINE__));
7360 			}
7361 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7362 		} else {
7363 			if (reg == BWN_PHY_RFOVER)
7364 				return (0x9b3);
7365 			if (reg == BWN_PHY_RFOVERVAL) {
7366 				if (extlna)
7367 					extlna |= 0x8000;
7368 				extlna |= (i << 8);
7369 				switch (lpd) {
7370 				case BWN_LPD(0, 1, 1):
7371 					return (0x8f92);
7372 				case BWN_LPD(0, 0, 1):
7373 					return (0x8092 | extlna);
7374 				case BWN_LPD(1, 0, 1):
7375 					return (0x2092 | extlna);
7376 				case BWN_LPD(1, 0, 0):
7377 					return (0x2093 | extlna);
7378 				}
7379 				KASSERT(0 == 1,
7380 				    ("%s:%d: fail", __func__, __LINE__));
7381 			}
7382 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7383 		}
7384 		return (0);
7385 	}
7386 
7387 	if ((phy->rev < 7) ||
7388 	    !(siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_EXTLNA)) {
7389 		if (reg == BWN_PHY_RFOVER) {
7390 			return (0x1b3);
7391 		} else if (reg == BWN_PHY_RFOVERVAL) {
7392 			switch (lpd) {
7393 			case BWN_LPD(0, 1, 1):
7394 				return (0x0fb2);
7395 			case BWN_LPD(0, 0, 1):
7396 				return (0x00b2);
7397 			case BWN_LPD(1, 0, 1):
7398 				return (0x30b2);
7399 			case BWN_LPD(1, 0, 0):
7400 				return (0x30b3);
7401 			}
7402 			KASSERT(0 == 1,
7403 			    ("%s:%d: fail", __func__, __LINE__));
7404 		}
7405 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7406 	} else {
7407 		if (reg == BWN_PHY_RFOVER) {
7408 			return (0x9b3);
7409 		} else if (reg == BWN_PHY_RFOVERVAL) {
7410 			switch (lpd) {
7411 			case BWN_LPD(0, 1, 1):
7412 				return (0x8fb2);
7413 			case BWN_LPD(0, 0, 1):
7414 				return (0x80b2);
7415 			case BWN_LPD(1, 0, 1):
7416 				return (0x20b2);
7417 			case BWN_LPD(1, 0, 0):
7418 				return (0x20b3);
7419 			}
7420 			KASSERT(0 == 1,
7421 			    ("%s:%d: fail", __func__, __LINE__));
7422 		}
7423 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7424 	}
7425 	return (0);
7426 }
7427 
7428 static void
7429 bwn_spu_workaround(struct bwn_mac *mac, uint8_t channel)
7430 {
7431 
7432 	if (mac->mac_phy.rf_ver != 0x2050 || mac->mac_phy.rf_rev >= 6)
7433 		return;
7434 	BWN_WRITE_2(mac, BWN_CHANNEL, (channel <= 10) ?
7435 	    bwn_phy_g_chan2freq(channel + 4) : bwn_phy_g_chan2freq(1));
7436 	DELAY(1000);
7437 	BWN_WRITE_2(mac, BWN_CHANNEL, bwn_phy_g_chan2freq(channel));
7438 }
7439 
7440 static int
7441 bwn_fw_gets(struct bwn_mac *mac, enum bwn_fwtype type)
7442 {
7443 	struct bwn_softc *sc = mac->mac_sc;
7444 	struct bwn_fw *fw = &mac->mac_fw;
7445 	const uint8_t rev = siba_get_revid(sc->sc_dev);
7446 	const char *filename;
7447 	uint32_t high;
7448 	int error;
7449 
7450 	/* microcode */
7451 	if (rev >= 5 && rev <= 10)
7452 		filename = "ucode5";
7453 	else if (rev >= 11 && rev <= 12)
7454 		filename = "ucode11";
7455 	else if (rev == 13)
7456 		filename = "ucode13";
7457 	else if (rev == 14)
7458 		filename = "ucode14";
7459 	else if (rev >= 15)
7460 		filename = "ucode15";
7461 	else {
7462 		device_printf(sc->sc_dev, "no ucode for rev %d\n", rev);
7463 		bwn_release_firmware(mac);
7464 		return (EOPNOTSUPP);
7465 	}
7466 	error = bwn_fw_get(mac, type, filename, &fw->ucode);
7467 	if (error) {
7468 		bwn_release_firmware(mac);
7469 		return (error);
7470 	}
7471 
7472 	/* PCM */
7473 	KASSERT(fw->no_pcmfile == 0, ("%s:%d fail", __func__, __LINE__));
7474 	if (rev >= 5 && rev <= 10) {
7475 		error = bwn_fw_get(mac, type, "pcm5", &fw->pcm);
7476 		if (error == ENOENT)
7477 			fw->no_pcmfile = 1;
7478 		else if (error) {
7479 			bwn_release_firmware(mac);
7480 			return (error);
7481 		}
7482 	} else if (rev < 11) {
7483 		device_printf(sc->sc_dev, "no PCM for rev %d\n", rev);
7484 		return (EOPNOTSUPP);
7485 	}
7486 
7487 	/* initvals */
7488 	high = siba_read_4(sc->sc_dev, SIBA_TGSHIGH);
7489 	switch (mac->mac_phy.type) {
7490 	case BWN_PHYTYPE_A:
7491 		if (rev < 5 || rev > 10)
7492 			goto fail1;
7493 		if (high & BWN_TGSHIGH_HAVE_2GHZ)
7494 			filename = "a0g1initvals5";
7495 		else
7496 			filename = "a0g0initvals5";
7497 		break;
7498 	case BWN_PHYTYPE_G:
7499 		if (rev >= 5 && rev <= 10)
7500 			filename = "b0g0initvals5";
7501 		else if (rev >= 13)
7502 			filename = "b0g0initvals13";
7503 		else
7504 			goto fail1;
7505 		break;
7506 	case BWN_PHYTYPE_LP:
7507 		if (rev == 13)
7508 			filename = "lp0initvals13";
7509 		else if (rev == 14)
7510 			filename = "lp0initvals14";
7511 		else if (rev >= 15)
7512 			filename = "lp0initvals15";
7513 		else
7514 			goto fail1;
7515 		break;
7516 	case BWN_PHYTYPE_N:
7517 		if (rev >= 11 && rev <= 12)
7518 			filename = "n0initvals11";
7519 		else
7520 			goto fail1;
7521 		break;
7522 	default:
7523 		goto fail1;
7524 	}
7525 	error = bwn_fw_get(mac, type, filename, &fw->initvals);
7526 	if (error) {
7527 		bwn_release_firmware(mac);
7528 		return (error);
7529 	}
7530 
7531 	/* bandswitch initvals */
7532 	switch (mac->mac_phy.type) {
7533 	case BWN_PHYTYPE_A:
7534 		if (rev >= 5 && rev <= 10) {
7535 			if (high & BWN_TGSHIGH_HAVE_2GHZ)
7536 				filename = "a0g1bsinitvals5";
7537 			else
7538 				filename = "a0g0bsinitvals5";
7539 		} else if (rev >= 11)
7540 			filename = NULL;
7541 		else
7542 			goto fail1;
7543 		break;
7544 	case BWN_PHYTYPE_G:
7545 		if (rev >= 5 && rev <= 10)
7546 			filename = "b0g0bsinitvals5";
7547 		else if (rev >= 11)
7548 			filename = NULL;
7549 		else
7550 			goto fail1;
7551 		break;
7552 	case BWN_PHYTYPE_LP:
7553 		if (rev == 13)
7554 			filename = "lp0bsinitvals13";
7555 		else if (rev == 14)
7556 			filename = "lp0bsinitvals14";
7557 		else if (rev >= 15)
7558 			filename = "lp0bsinitvals15";
7559 		else
7560 			goto fail1;
7561 		break;
7562 	case BWN_PHYTYPE_N:
7563 		if (rev >= 11 && rev <= 12)
7564 			filename = "n0bsinitvals11";
7565 		else
7566 			goto fail1;
7567 		break;
7568 	default:
7569 		goto fail1;
7570 	}
7571 	error = bwn_fw_get(mac, type, filename, &fw->initvals_band);
7572 	if (error) {
7573 		bwn_release_firmware(mac);
7574 		return (error);
7575 	}
7576 	return (0);
7577 fail1:
7578 	device_printf(sc->sc_dev, "no INITVALS for rev %d\n", rev);
7579 	bwn_release_firmware(mac);
7580 	return (EOPNOTSUPP);
7581 }
7582 
7583 static int
7584 bwn_fw_get(struct bwn_mac *mac, enum bwn_fwtype type,
7585     const char *name, struct bwn_fwfile *bfw)
7586 {
7587 	const struct bwn_fwhdr *hdr;
7588 	struct bwn_softc *sc = mac->mac_sc;
7589 	const struct firmware *fw;
7590 	char namebuf[64];
7591 
7592 	if (name == NULL) {
7593 		bwn_do_release_fw(bfw);
7594 		return (0);
7595 	}
7596 	if (bfw->filename != NULL) {
7597 		if (bfw->type == type && (strcmp(bfw->filename, name) == 0))
7598 			return (0);
7599 		bwn_do_release_fw(bfw);
7600 	}
7601 
7602 	snprintf(namebuf, sizeof(namebuf), "bwn%s_v4_%s%s",
7603 	    (type == BWN_FWTYPE_OPENSOURCE) ? "-open" : "",
7604 	    (mac->mac_phy.type == BWN_PHYTYPE_LP) ? "lp_" : "", name);
7605 	/* XXX Sleeping on "fwload" with the non-sleepable locks held */
7606 	fw = firmware_get(namebuf);
7607 	if (fw == NULL) {
7608 		device_printf(sc->sc_dev, "the fw file(%s) not found\n",
7609 		    namebuf);
7610 		return (ENOENT);
7611 	}
7612 	if (fw->datasize < sizeof(struct bwn_fwhdr))
7613 		goto fail;
7614 	hdr = (const struct bwn_fwhdr *)(fw->data);
7615 	switch (hdr->type) {
7616 	case BWN_FWTYPE_UCODE:
7617 	case BWN_FWTYPE_PCM:
7618 		if (be32toh(hdr->size) !=
7619 		    (fw->datasize - sizeof(struct bwn_fwhdr)))
7620 			goto fail;
7621 		/* FALLTHROUGH */
7622 	case BWN_FWTYPE_IV:
7623 		if (hdr->ver != 1)
7624 			goto fail;
7625 		break;
7626 	default:
7627 		goto fail;
7628 	}
7629 	bfw->filename = name;
7630 	bfw->fw = fw;
7631 	bfw->type = type;
7632 	return (0);
7633 fail:
7634 	device_printf(sc->sc_dev, "the fw file(%s) format error\n", namebuf);
7635 	if (fw != NULL)
7636 		firmware_put(fw, FIRMWARE_UNLOAD);
7637 	return (EPROTO);
7638 }
7639 
7640 static void
7641 bwn_release_firmware(struct bwn_mac *mac)
7642 {
7643 
7644 	bwn_do_release_fw(&mac->mac_fw.ucode);
7645 	bwn_do_release_fw(&mac->mac_fw.pcm);
7646 	bwn_do_release_fw(&mac->mac_fw.initvals);
7647 	bwn_do_release_fw(&mac->mac_fw.initvals_band);
7648 }
7649 
7650 static void
7651 bwn_do_release_fw(struct bwn_fwfile *bfw)
7652 {
7653 
7654 	if (bfw->fw != NULL)
7655 		firmware_put(bfw->fw, FIRMWARE_UNLOAD);
7656 	bfw->fw = NULL;
7657 	bfw->filename = NULL;
7658 }
7659 
7660 static int
7661 bwn_fw_loaducode(struct bwn_mac *mac)
7662 {
7663 #define	GETFWOFFSET(fwp, offset)	\
7664 	((const uint32_t *)((const char *)fwp.fw->data + offset))
7665 #define	GETFWSIZE(fwp, offset)	\
7666 	((fwp.fw->datasize - offset) / sizeof(uint32_t))
7667 	struct bwn_softc *sc = mac->mac_sc;
7668 	const uint32_t *data;
7669 	unsigned int i;
7670 	uint32_t ctl;
7671 	uint16_t date, fwcaps, time;
7672 	int error = 0;
7673 
7674 	ctl = BWN_READ_4(mac, BWN_MACCTL);
7675 	ctl |= BWN_MACCTL_MCODE_JMP0;
7676 	KASSERT(!(ctl & BWN_MACCTL_MCODE_RUN), ("%s:%d: fail", __func__,
7677 	    __LINE__));
7678 	BWN_WRITE_4(mac, BWN_MACCTL, ctl);
7679 	for (i = 0; i < 64; i++)
7680 		bwn_shm_write_2(mac, BWN_SCRATCH, i, 0);
7681 	for (i = 0; i < 4096; i += 2)
7682 		bwn_shm_write_2(mac, BWN_SHARED, i, 0);
7683 
7684 	data = GETFWOFFSET(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7685 	bwn_shm_ctlword(mac, BWN_UCODE | BWN_SHARED_AUTOINC, 0x0000);
7686 	for (i = 0; i < GETFWSIZE(mac->mac_fw.ucode, sizeof(struct bwn_fwhdr));
7687 	     i++) {
7688 		BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7689 		DELAY(10);
7690 	}
7691 
7692 	if (mac->mac_fw.pcm.fw) {
7693 		data = GETFWOFFSET(mac->mac_fw.pcm, sizeof(struct bwn_fwhdr));
7694 		bwn_shm_ctlword(mac, BWN_HW, 0x01ea);
7695 		BWN_WRITE_4(mac, BWN_SHM_DATA, 0x00004000);
7696 		bwn_shm_ctlword(mac, BWN_HW, 0x01eb);
7697 		for (i = 0; i < GETFWSIZE(mac->mac_fw.pcm,
7698 		    sizeof(struct bwn_fwhdr)); i++) {
7699 			BWN_WRITE_4(mac, BWN_SHM_DATA, be32toh(data[i]));
7700 			DELAY(10);
7701 		}
7702 	}
7703 
7704 	BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_ALL);
7705 	BWN_WRITE_4(mac, BWN_MACCTL,
7706 	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_JMP0) |
7707 	    BWN_MACCTL_MCODE_RUN);
7708 
7709 	for (i = 0; i < 21; i++) {
7710 		if (BWN_READ_4(mac, BWN_INTR_REASON) == BWN_INTR_MAC_SUSPENDED)
7711 			break;
7712 		if (i >= 20) {
7713 			device_printf(sc->sc_dev, "ucode timeout\n");
7714 			error = ENXIO;
7715 			goto error;
7716 		}
7717 		DELAY(50000);
7718 	}
7719 	BWN_READ_4(mac, BWN_INTR_REASON);
7720 
7721 	mac->mac_fw.rev = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_REV);
7722 	if (mac->mac_fw.rev <= 0x128) {
7723 		device_printf(sc->sc_dev, "the firmware is too old\n");
7724 		error = EOPNOTSUPP;
7725 		goto error;
7726 	}
7727 	mac->mac_fw.patch = bwn_shm_read_2(mac, BWN_SHARED,
7728 	    BWN_SHARED_UCODE_PATCH);
7729 	date = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_DATE);
7730 	mac->mac_fw.opensource = (date == 0xffff);
7731 	if (bwn_wme != 0)
7732 		mac->mac_flags |= BWN_MAC_FLAG_WME;
7733 	mac->mac_flags |= BWN_MAC_FLAG_HWCRYPTO;
7734 
7735 	time = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_UCODE_TIME);
7736 	if (mac->mac_fw.opensource == 0) {
7737 		device_printf(sc->sc_dev,
7738 		    "firmware version (rev %u patch %u date %#x time %#x)\n",
7739 		    mac->mac_fw.rev, mac->mac_fw.patch, date, time);
7740 		if (mac->mac_fw.no_pcmfile)
7741 			device_printf(sc->sc_dev,
7742 			    "no HW crypto acceleration due to pcm5\n");
7743 	} else {
7744 		mac->mac_fw.patch = time;
7745 		fwcaps = bwn_fwcaps_read(mac);
7746 		if (!(fwcaps & BWN_FWCAPS_HWCRYPTO) || mac->mac_fw.no_pcmfile) {
7747 			device_printf(sc->sc_dev,
7748 			    "disabling HW crypto acceleration\n");
7749 			mac->mac_flags &= ~BWN_MAC_FLAG_HWCRYPTO;
7750 		}
7751 		if (!(fwcaps & BWN_FWCAPS_WME)) {
7752 			device_printf(sc->sc_dev, "disabling WME support\n");
7753 			mac->mac_flags &= ~BWN_MAC_FLAG_WME;
7754 		}
7755 	}
7756 
7757 	if (BWN_ISOLDFMT(mac))
7758 		device_printf(sc->sc_dev, "using old firmware image\n");
7759 
7760 	return (0);
7761 
7762 error:
7763 	BWN_WRITE_4(mac, BWN_MACCTL,
7764 	    (BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_MCODE_RUN) |
7765 	    BWN_MACCTL_MCODE_JMP0);
7766 
7767 	return (error);
7768 #undef GETFWSIZE
7769 #undef GETFWOFFSET
7770 }
7771 
7772 /* OpenFirmware only */
7773 static uint16_t
7774 bwn_fwcaps_read(struct bwn_mac *mac)
7775 {
7776 
7777 	KASSERT(mac->mac_fw.opensource == 1,
7778 	    ("%s:%d: fail", __func__, __LINE__));
7779 	return (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_FWCAPS));
7780 }
7781 
7782 static int
7783 bwn_fwinitvals_write(struct bwn_mac *mac, const struct bwn_fwinitvals *ivals,
7784     size_t count, size_t array_size)
7785 {
7786 #define	GET_NEXTIV16(iv)						\
7787 	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7788 	    sizeof(uint16_t) + sizeof(uint16_t)))
7789 #define	GET_NEXTIV32(iv)						\
7790 	((const struct bwn_fwinitvals *)((const uint8_t *)(iv) +	\
7791 	    sizeof(uint16_t) + sizeof(uint32_t)))
7792 	struct bwn_softc *sc = mac->mac_sc;
7793 	const struct bwn_fwinitvals *iv;
7794 	uint16_t offset;
7795 	size_t i;
7796 	uint8_t bit32;
7797 
7798 	KASSERT(sizeof(struct bwn_fwinitvals) == 6,
7799 	    ("%s:%d: fail", __func__, __LINE__));
7800 	iv = ivals;
7801 	for (i = 0; i < count; i++) {
7802 		if (array_size < sizeof(iv->offset_size))
7803 			goto fail;
7804 		array_size -= sizeof(iv->offset_size);
7805 		offset = be16toh(iv->offset_size);
7806 		bit32 = (offset & BWN_FWINITVALS_32BIT) ? 1 : 0;
7807 		offset &= BWN_FWINITVALS_OFFSET_MASK;
7808 		if (offset >= 0x1000)
7809 			goto fail;
7810 		if (bit32) {
7811 			if (array_size < sizeof(iv->data.d32))
7812 				goto fail;
7813 			array_size -= sizeof(iv->data.d32);
7814 			BWN_WRITE_4(mac, offset, be32toh(iv->data.d32));
7815 			iv = GET_NEXTIV32(iv);
7816 		} else {
7817 
7818 			if (array_size < sizeof(iv->data.d16))
7819 				goto fail;
7820 			array_size -= sizeof(iv->data.d16);
7821 			BWN_WRITE_2(mac, offset, be16toh(iv->data.d16));
7822 
7823 			iv = GET_NEXTIV16(iv);
7824 		}
7825 	}
7826 	if (array_size != 0)
7827 		goto fail;
7828 	return (0);
7829 fail:
7830 	device_printf(sc->sc_dev, "initvals: invalid format\n");
7831 	return (EPROTO);
7832 #undef GET_NEXTIV16
7833 #undef GET_NEXTIV32
7834 }
7835 
7836 static int
7837 bwn_switch_channel(struct bwn_mac *mac, int chan)
7838 {
7839 	struct bwn_phy *phy = &(mac->mac_phy);
7840 	struct bwn_softc *sc = mac->mac_sc;
7841 	struct ieee80211com *ic = &sc->sc_ic;
7842 	uint16_t channelcookie, savedcookie;
7843 	int error;
7844 
7845 	if (chan == 0xffff)
7846 		chan = phy->get_default_chan(mac);
7847 
7848 	channelcookie = chan;
7849 	if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan))
7850 		channelcookie |= 0x100;
7851 	savedcookie = bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_CHAN);
7852 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, channelcookie);
7853 	error = phy->switch_channel(mac, chan);
7854 	if (error)
7855 		goto fail;
7856 
7857 	mac->mac_phy.chan = chan;
7858 	DELAY(8000);
7859 	return (0);
7860 fail:
7861 	device_printf(sc->sc_dev, "failed to switch channel\n");
7862 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_CHAN, savedcookie);
7863 	return (error);
7864 }
7865 
7866 static uint16_t
7867 bwn_ant2phy(int antenna)
7868 {
7869 
7870 	switch (antenna) {
7871 	case BWN_ANT0:
7872 		return (BWN_TX_PHY_ANT0);
7873 	case BWN_ANT1:
7874 		return (BWN_TX_PHY_ANT1);
7875 	case BWN_ANT2:
7876 		return (BWN_TX_PHY_ANT2);
7877 	case BWN_ANT3:
7878 		return (BWN_TX_PHY_ANT3);
7879 	case BWN_ANTAUTO:
7880 		return (BWN_TX_PHY_ANT01AUTO);
7881 	}
7882 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
7883 	return (0);
7884 }
7885 
7886 static void
7887 bwn_wme_load(struct bwn_mac *mac)
7888 {
7889 	struct bwn_softc *sc = mac->mac_sc;
7890 	int i;
7891 
7892 	KASSERT(N(bwn_wme_shm_offsets) == N(sc->sc_wmeParams),
7893 	    ("%s:%d: fail", __func__, __LINE__));
7894 
7895 	bwn_mac_suspend(mac);
7896 	for (i = 0; i < N(sc->sc_wmeParams); i++)
7897 		bwn_wme_loadparams(mac, &(sc->sc_wmeParams[i]),
7898 		    bwn_wme_shm_offsets[i]);
7899 	bwn_mac_enable(mac);
7900 }
7901 
7902 static void
7903 bwn_wme_loadparams(struct bwn_mac *mac,
7904     const struct wmeParams *p, uint16_t shm_offset)
7905 {
7906 #define	SM(_v, _f)      (((_v) << _f##_S) & _f)
7907 	struct bwn_softc *sc = mac->mac_sc;
7908 	uint16_t params[BWN_NR_WMEPARAMS];
7909 	int slot, tmp;
7910 	unsigned int i;
7911 
7912 	slot = BWN_READ_2(mac, BWN_RNG) &
7913 	    SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
7914 
7915 	memset(&params, 0, sizeof(params));
7916 
7917 	DPRINTF(sc, BWN_DEBUG_WME, "wmep_txopLimit %d wmep_logcwmin %d "
7918 	    "wmep_logcwmax %d wmep_aifsn %d\n", p->wmep_txopLimit,
7919 	    p->wmep_logcwmin, p->wmep_logcwmax, p->wmep_aifsn);
7920 
7921 	params[BWN_WMEPARAM_TXOP] = p->wmep_txopLimit * 32;
7922 	params[BWN_WMEPARAM_CWMIN] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
7923 	params[BWN_WMEPARAM_CWMAX] = SM(p->wmep_logcwmax, WME_PARAM_LOGCWMAX);
7924 	params[BWN_WMEPARAM_CWCUR] = SM(p->wmep_logcwmin, WME_PARAM_LOGCWMIN);
7925 	params[BWN_WMEPARAM_AIFS] = p->wmep_aifsn;
7926 	params[BWN_WMEPARAM_BSLOTS] = slot;
7927 	params[BWN_WMEPARAM_REGGAP] = slot + p->wmep_aifsn;
7928 
7929 	for (i = 0; i < N(params); i++) {
7930 		if (i == BWN_WMEPARAM_STATUS) {
7931 			tmp = bwn_shm_read_2(mac, BWN_SHARED,
7932 			    shm_offset + (i * 2));
7933 			tmp |= 0x100;
7934 			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
7935 			    tmp);
7936 		} else {
7937 			bwn_shm_write_2(mac, BWN_SHARED, shm_offset + (i * 2),
7938 			    params[i]);
7939 		}
7940 	}
7941 }
7942 
7943 static void
7944 bwn_mac_write_bssid(struct bwn_mac *mac)
7945 {
7946 	struct bwn_softc *sc = mac->mac_sc;
7947 	uint32_t tmp;
7948 	int i;
7949 	uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
7950 
7951 	bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
7952 	memcpy(mac_bssid, sc->sc_ic.ic_macaddr, IEEE80211_ADDR_LEN);
7953 	memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
7954 	    IEEE80211_ADDR_LEN);
7955 
7956 	for (i = 0; i < N(mac_bssid); i += sizeof(uint32_t)) {
7957 		tmp = (uint32_t) (mac_bssid[i + 0]);
7958 		tmp |= (uint32_t) (mac_bssid[i + 1]) << 8;
7959 		tmp |= (uint32_t) (mac_bssid[i + 2]) << 16;
7960 		tmp |= (uint32_t) (mac_bssid[i + 3]) << 24;
7961 		bwn_ram_write(mac, 0x20 + i, tmp);
7962 	}
7963 }
7964 
7965 static void
7966 bwn_mac_setfilter(struct bwn_mac *mac, uint16_t offset,
7967     const uint8_t *macaddr)
7968 {
7969 	static const uint8_t zero[IEEE80211_ADDR_LEN] = { 0 };
7970 	uint16_t data;
7971 
7972 	if (!mac)
7973 		macaddr = zero;
7974 
7975 	offset |= 0x0020;
7976 	BWN_WRITE_2(mac, BWN_MACFILTER_CONTROL, offset);
7977 
7978 	data = macaddr[0];
7979 	data |= macaddr[1] << 8;
7980 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
7981 	data = macaddr[2];
7982 	data |= macaddr[3] << 8;
7983 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
7984 	data = macaddr[4];
7985 	data |= macaddr[5] << 8;
7986 	BWN_WRITE_2(mac, BWN_MACFILTER_DATA, data);
7987 }
7988 
7989 static void
7990 bwn_key_dowrite(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
7991     const uint8_t *key, size_t key_len, const uint8_t *mac_addr)
7992 {
7993 	uint8_t buf[BWN_SEC_KEYSIZE] = { 0, };
7994 	uint8_t per_sta_keys_start = 8;
7995 
7996 	if (BWN_SEC_NEWAPI(mac))
7997 		per_sta_keys_start = 4;
7998 
7999 	KASSERT(index < mac->mac_max_nr_keys,
8000 	    ("%s:%d: fail", __func__, __LINE__));
8001 	KASSERT(key_len <= BWN_SEC_KEYSIZE,
8002 	    ("%s:%d: fail", __func__, __LINE__));
8003 
8004 	if (index >= per_sta_keys_start)
8005 		bwn_key_macwrite(mac, index, NULL);
8006 	if (key)
8007 		memcpy(buf, key, key_len);
8008 	bwn_key_write(mac, index, algorithm, buf);
8009 	if (index >= per_sta_keys_start)
8010 		bwn_key_macwrite(mac, index, mac_addr);
8011 
8012 	mac->mac_key[index].algorithm = algorithm;
8013 }
8014 
8015 static void
8016 bwn_key_macwrite(struct bwn_mac *mac, uint8_t index, const uint8_t *addr)
8017 {
8018 	struct bwn_softc *sc = mac->mac_sc;
8019 	uint32_t addrtmp[2] = { 0, 0 };
8020 	uint8_t start = 8;
8021 
8022 	if (BWN_SEC_NEWAPI(mac))
8023 		start = 4;
8024 
8025 	KASSERT(index >= start,
8026 	    ("%s:%d: fail", __func__, __LINE__));
8027 	index -= start;
8028 
8029 	if (addr) {
8030 		addrtmp[0] = addr[0];
8031 		addrtmp[0] |= ((uint32_t) (addr[1]) << 8);
8032 		addrtmp[0] |= ((uint32_t) (addr[2]) << 16);
8033 		addrtmp[0] |= ((uint32_t) (addr[3]) << 24);
8034 		addrtmp[1] = addr[4];
8035 		addrtmp[1] |= ((uint32_t) (addr[5]) << 8);
8036 	}
8037 
8038 	if (siba_get_revid(sc->sc_dev) >= 5) {
8039 		bwn_shm_write_4(mac, BWN_RCMTA, (index * 2) + 0, addrtmp[0]);
8040 		bwn_shm_write_2(mac, BWN_RCMTA, (index * 2) + 1, addrtmp[1]);
8041 	} else {
8042 		if (index >= 8) {
8043 			bwn_shm_write_4(mac, BWN_SHARED,
8044 			    BWN_SHARED_PSM + (index * 6) + 0, addrtmp[0]);
8045 			bwn_shm_write_2(mac, BWN_SHARED,
8046 			    BWN_SHARED_PSM + (index * 6) + 4, addrtmp[1]);
8047 		}
8048 	}
8049 }
8050 
8051 static void
8052 bwn_key_write(struct bwn_mac *mac, uint8_t index, uint8_t algorithm,
8053     const uint8_t *key)
8054 {
8055 	unsigned int i;
8056 	uint32_t offset;
8057 	uint16_t kidx, value;
8058 
8059 	kidx = BWN_SEC_KEY2FW(mac, index);
8060 	bwn_shm_write_2(mac, BWN_SHARED,
8061 	    BWN_SHARED_KEYIDX_BLOCK + (kidx * 2), (kidx << 4) | algorithm);
8062 
8063 	offset = mac->mac_ktp + (index * BWN_SEC_KEYSIZE);
8064 	for (i = 0; i < BWN_SEC_KEYSIZE; i += 2) {
8065 		value = key[i];
8066 		value |= (uint16_t)(key[i + 1]) << 8;
8067 		bwn_shm_write_2(mac, BWN_SHARED, offset + i, value);
8068 	}
8069 }
8070 
8071 static void
8072 bwn_phy_exit(struct bwn_mac *mac)
8073 {
8074 
8075 	mac->mac_phy.rf_onoff(mac, 0);
8076 	if (mac->mac_phy.exit != NULL)
8077 		mac->mac_phy.exit(mac);
8078 }
8079 
8080 static void
8081 bwn_dma_free(struct bwn_mac *mac)
8082 {
8083 	struct bwn_dma *dma;
8084 
8085 	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
8086 		return;
8087 	dma = &mac->mac_method.dma;
8088 
8089 	bwn_dma_ringfree(&dma->rx);
8090 	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
8091 	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
8092 	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
8093 	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
8094 	bwn_dma_ringfree(&dma->mcast);
8095 }
8096 
8097 static void
8098 bwn_core_stop(struct bwn_mac *mac)
8099 {
8100 	struct bwn_softc *sc = mac->mac_sc;
8101 
8102 	BWN_ASSERT_LOCKED(sc);
8103 
8104 	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8105 		return;
8106 
8107 	callout_stop(&sc->sc_rfswitch_ch);
8108 	callout_stop(&sc->sc_task_ch);
8109 	callout_stop(&sc->sc_watchdog_ch);
8110 	sc->sc_watchdog_timer = 0;
8111 	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8112 	BWN_READ_4(mac, BWN_INTR_MASK);
8113 	bwn_mac_suspend(mac);
8114 
8115 	mac->mac_status = BWN_MAC_STATUS_INITED;
8116 }
8117 
8118 static int
8119 bwn_switch_band(struct bwn_softc *sc, struct ieee80211_channel *chan)
8120 {
8121 	struct bwn_mac *up_dev = NULL;
8122 	struct bwn_mac *down_dev;
8123 	struct bwn_mac *mac;
8124 	int err, status;
8125 	uint8_t gmode;
8126 
8127 	BWN_ASSERT_LOCKED(sc);
8128 
8129 	TAILQ_FOREACH(mac, &sc->sc_maclist, mac_list) {
8130 		if (IEEE80211_IS_CHAN_2GHZ(chan) &&
8131 		    mac->mac_phy.supports_2ghz) {
8132 			up_dev = mac;
8133 			gmode = 1;
8134 		} else if (IEEE80211_IS_CHAN_5GHZ(chan) &&
8135 		    mac->mac_phy.supports_5ghz) {
8136 			up_dev = mac;
8137 			gmode = 0;
8138 		} else {
8139 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8140 			return (EINVAL);
8141 		}
8142 		if (up_dev != NULL)
8143 			break;
8144 	}
8145 	if (up_dev == NULL) {
8146 		device_printf(sc->sc_dev, "Could not find a device\n");
8147 		return (ENODEV);
8148 	}
8149 	if (up_dev == sc->sc_curmac && sc->sc_curmac->mac_phy.gmode == gmode)
8150 		return (0);
8151 
8152 	device_printf(sc->sc_dev, "switching to %s-GHz band\n",
8153 	    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8154 
8155 	down_dev = sc->sc_curmac;
8156 	status = down_dev->mac_status;
8157 	if (status >= BWN_MAC_STATUS_STARTED)
8158 		bwn_core_stop(down_dev);
8159 	if (status >= BWN_MAC_STATUS_INITED)
8160 		bwn_core_exit(down_dev);
8161 
8162 	if (down_dev != up_dev)
8163 		bwn_phy_reset(down_dev);
8164 
8165 	up_dev->mac_phy.gmode = gmode;
8166 	if (status >= BWN_MAC_STATUS_INITED) {
8167 		err = bwn_core_init(up_dev);
8168 		if (err) {
8169 			device_printf(sc->sc_dev,
8170 			    "fatal: failed to initialize for %s-GHz\n",
8171 			    IEEE80211_IS_CHAN_2GHZ(chan) ? "2" : "5");
8172 			goto fail;
8173 		}
8174 	}
8175 	if (status >= BWN_MAC_STATUS_STARTED)
8176 		bwn_core_start(up_dev);
8177 	KASSERT(up_dev->mac_status == status, ("%s: fail", __func__));
8178 	sc->sc_curmac = up_dev;
8179 
8180 	return (0);
8181 fail:
8182 	sc->sc_curmac = NULL;
8183 	return (err);
8184 }
8185 
8186 static void
8187 bwn_rf_turnon(struct bwn_mac *mac)
8188 {
8189 
8190 	bwn_mac_suspend(mac);
8191 	mac->mac_phy.rf_onoff(mac, 1);
8192 	mac->mac_phy.rf_on = 1;
8193 	bwn_mac_enable(mac);
8194 }
8195 
8196 static void
8197 bwn_rf_turnoff(struct bwn_mac *mac)
8198 {
8199 
8200 	bwn_mac_suspend(mac);
8201 	mac->mac_phy.rf_onoff(mac, 0);
8202 	mac->mac_phy.rf_on = 0;
8203 	bwn_mac_enable(mac);
8204 }
8205 
8206 static void
8207 bwn_phy_reset(struct bwn_mac *mac)
8208 {
8209 	struct bwn_softc *sc = mac->mac_sc;
8210 
8211 	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8212 	    ((siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~BWN_TGSLOW_SUPPORT_G) |
8213 	     BWN_TGSLOW_PHYRESET) | SIBA_TGSLOW_FGC);
8214 	DELAY(1000);
8215 	siba_write_4(sc->sc_dev, SIBA_TGSLOW,
8216 	    (siba_read_4(sc->sc_dev, SIBA_TGSLOW) & ~SIBA_TGSLOW_FGC) |
8217 	    BWN_TGSLOW_PHYRESET);
8218 	DELAY(1000);
8219 }
8220 
8221 static int
8222 bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
8223 {
8224 	struct bwn_vap *bvp = BWN_VAP(vap);
8225 	struct ieee80211com *ic= vap->iv_ic;
8226 	enum ieee80211_state ostate = vap->iv_state;
8227 	struct bwn_softc *sc = ic->ic_softc;
8228 	struct bwn_mac *mac = sc->sc_curmac;
8229 	int error;
8230 
8231 	DPRINTF(sc, BWN_DEBUG_STATE, "%s: %s -> %s\n", __func__,
8232 	    ieee80211_state_name[vap->iv_state],
8233 	    ieee80211_state_name[nstate]);
8234 
8235 	error = bvp->bv_newstate(vap, nstate, arg);
8236 	if (error != 0)
8237 		return (error);
8238 
8239 	BWN_LOCK(sc);
8240 
8241 	bwn_led_newstate(mac, nstate);
8242 
8243 	/*
8244 	 * Clear the BSSID when we stop a STA
8245 	 */
8246 	if (vap->iv_opmode == IEEE80211_M_STA) {
8247 		if (ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_RUN) {
8248 			/*
8249 			 * Clear out the BSSID.  If we reassociate to
8250 			 * the same AP, this will reinialize things
8251 			 * correctly...
8252 			 */
8253 			if (ic->ic_opmode == IEEE80211_M_STA &&
8254 			    (sc->sc_flags & BWN_FLAG_INVALID) == 0) {
8255 				memset(sc->sc_bssid, 0, IEEE80211_ADDR_LEN);
8256 				bwn_set_macaddr(mac);
8257 			}
8258 		}
8259 	}
8260 
8261 	if (vap->iv_opmode == IEEE80211_M_MONITOR ||
8262 	    vap->iv_opmode == IEEE80211_M_AHDEMO) {
8263 		/* XXX nothing to do? */
8264 	} else if (nstate == IEEE80211_S_RUN) {
8265 		memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
8266 		bwn_set_opmode(mac);
8267 		bwn_set_pretbtt(mac);
8268 		bwn_spu_setdelay(mac, 0);
8269 		bwn_set_macaddr(mac);
8270 	}
8271 
8272 	BWN_UNLOCK(sc);
8273 
8274 	return (error);
8275 }
8276 
8277 static void
8278 bwn_set_pretbtt(struct bwn_mac *mac)
8279 {
8280 	struct bwn_softc *sc = mac->mac_sc;
8281 	struct ieee80211com *ic = &sc->sc_ic;
8282 	uint16_t pretbtt;
8283 
8284 	if (ic->ic_opmode == IEEE80211_M_IBSS)
8285 		pretbtt = 2;
8286 	else
8287 		pretbtt = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 120 : 250;
8288 	bwn_shm_write_2(mac, BWN_SHARED, BWN_SHARED_PRETBTT, pretbtt);
8289 	BWN_WRITE_2(mac, BWN_TSF_CFP_PRETBTT, pretbtt);
8290 }
8291 
8292 static int
8293 bwn_intr(void *arg)
8294 {
8295 	struct bwn_mac *mac = arg;
8296 	struct bwn_softc *sc = mac->mac_sc;
8297 	uint32_t reason;
8298 
8299 	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8300 	    (sc->sc_flags & BWN_FLAG_INVALID))
8301 		return (FILTER_STRAY);
8302 
8303 	reason = BWN_READ_4(mac, BWN_INTR_REASON);
8304 	if (reason == 0xffffffff)	/* shared IRQ */
8305 		return (FILTER_STRAY);
8306 	reason &= mac->mac_intr_mask;
8307 	if (reason == 0)
8308 		return (FILTER_HANDLED);
8309 
8310 	mac->mac_reason[0] = BWN_READ_4(mac, BWN_DMA0_REASON) & 0x0001dc00;
8311 	mac->mac_reason[1] = BWN_READ_4(mac, BWN_DMA1_REASON) & 0x0000dc00;
8312 	mac->mac_reason[2] = BWN_READ_4(mac, BWN_DMA2_REASON) & 0x0000dc00;
8313 	mac->mac_reason[3] = BWN_READ_4(mac, BWN_DMA3_REASON) & 0x0001dc00;
8314 	mac->mac_reason[4] = BWN_READ_4(mac, BWN_DMA4_REASON) & 0x0000dc00;
8315 	BWN_WRITE_4(mac, BWN_INTR_REASON, reason);
8316 	BWN_WRITE_4(mac, BWN_DMA0_REASON, mac->mac_reason[0]);
8317 	BWN_WRITE_4(mac, BWN_DMA1_REASON, mac->mac_reason[1]);
8318 	BWN_WRITE_4(mac, BWN_DMA2_REASON, mac->mac_reason[2]);
8319 	BWN_WRITE_4(mac, BWN_DMA3_REASON, mac->mac_reason[3]);
8320 	BWN_WRITE_4(mac, BWN_DMA4_REASON, mac->mac_reason[4]);
8321 
8322 	/* Disable interrupts. */
8323 	BWN_WRITE_4(mac, BWN_INTR_MASK, 0);
8324 
8325 	mac->mac_reason_intr = reason;
8326 
8327 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8328 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8329 
8330 	taskqueue_enqueue_fast(sc->sc_tq, &mac->mac_intrtask);
8331 	return (FILTER_HANDLED);
8332 }
8333 
8334 static void
8335 bwn_intrtask(void *arg, int npending)
8336 {
8337 	struct bwn_mac *mac = arg;
8338 	struct bwn_softc *sc = mac->mac_sc;
8339 	uint32_t merged = 0;
8340 	int i, tx = 0, rx = 0;
8341 
8342 	BWN_LOCK(sc);
8343 	if (mac->mac_status < BWN_MAC_STATUS_STARTED ||
8344 	    (sc->sc_flags & BWN_FLAG_INVALID)) {
8345 		BWN_UNLOCK(sc);
8346 		return;
8347 	}
8348 
8349 	for (i = 0; i < N(mac->mac_reason); i++)
8350 		merged |= mac->mac_reason[i];
8351 
8352 	if (mac->mac_reason_intr & BWN_INTR_MAC_TXERR)
8353 		device_printf(sc->sc_dev, "MAC trans error\n");
8354 
8355 	if (mac->mac_reason_intr & BWN_INTR_PHY_TXERR) {
8356 		DPRINTF(sc, BWN_DEBUG_INTR, "%s: PHY trans error\n", __func__);
8357 		mac->mac_phy.txerrors--;
8358 		if (mac->mac_phy.txerrors == 0) {
8359 			mac->mac_phy.txerrors = BWN_TXERROR_MAX;
8360 			bwn_restart(mac, "PHY TX errors");
8361 		}
8362 	}
8363 
8364 	if (merged & (BWN_DMAINTR_FATALMASK | BWN_DMAINTR_NONFATALMASK)) {
8365 		if (merged & BWN_DMAINTR_FATALMASK) {
8366 			device_printf(sc->sc_dev,
8367 			    "Fatal DMA error: %#x %#x %#x %#x %#x %#x\n",
8368 			    mac->mac_reason[0], mac->mac_reason[1],
8369 			    mac->mac_reason[2], mac->mac_reason[3],
8370 			    mac->mac_reason[4], mac->mac_reason[5]);
8371 			bwn_restart(mac, "DMA error");
8372 			BWN_UNLOCK(sc);
8373 			return;
8374 		}
8375 		if (merged & BWN_DMAINTR_NONFATALMASK) {
8376 			device_printf(sc->sc_dev,
8377 			    "DMA error: %#x %#x %#x %#x %#x %#x\n",
8378 			    mac->mac_reason[0], mac->mac_reason[1],
8379 			    mac->mac_reason[2], mac->mac_reason[3],
8380 			    mac->mac_reason[4], mac->mac_reason[5]);
8381 		}
8382 	}
8383 
8384 	if (mac->mac_reason_intr & BWN_INTR_UCODE_DEBUG)
8385 		bwn_intr_ucode_debug(mac);
8386 	if (mac->mac_reason_intr & BWN_INTR_TBTT_INDI)
8387 		bwn_intr_tbtt_indication(mac);
8388 	if (mac->mac_reason_intr & BWN_INTR_ATIM_END)
8389 		bwn_intr_atim_end(mac);
8390 	if (mac->mac_reason_intr & BWN_INTR_BEACON)
8391 		bwn_intr_beacon(mac);
8392 	if (mac->mac_reason_intr & BWN_INTR_PMQ)
8393 		bwn_intr_pmq(mac);
8394 	if (mac->mac_reason_intr & BWN_INTR_NOISESAMPLE_OK)
8395 		bwn_intr_noise(mac);
8396 
8397 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8398 		if (mac->mac_reason[0] & BWN_DMAINTR_RX_DONE) {
8399 			bwn_dma_rx(mac->mac_method.dma.rx);
8400 			rx = 1;
8401 		}
8402 	} else
8403 		rx = bwn_pio_rx(&mac->mac_method.pio.rx);
8404 
8405 	KASSERT(!(mac->mac_reason[1] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8406 	KASSERT(!(mac->mac_reason[2] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8407 	KASSERT(!(mac->mac_reason[3] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8408 	KASSERT(!(mac->mac_reason[4] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8409 	KASSERT(!(mac->mac_reason[5] & BWN_DMAINTR_RX_DONE), ("%s", __func__));
8410 
8411 	if (mac->mac_reason_intr & BWN_INTR_TX_OK) {
8412 		bwn_intr_txeof(mac);
8413 		tx = 1;
8414 	}
8415 
8416 	BWN_WRITE_4(mac, BWN_INTR_MASK, mac->mac_intr_mask);
8417 
8418 	if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
8419 		int evt = BWN_LED_EVENT_NONE;
8420 
8421 		if (tx && rx) {
8422 			if (sc->sc_rx_rate > sc->sc_tx_rate)
8423 				evt = BWN_LED_EVENT_RX;
8424 			else
8425 				evt = BWN_LED_EVENT_TX;
8426 		} else if (tx) {
8427 			evt = BWN_LED_EVENT_TX;
8428 		} else if (rx) {
8429 			evt = BWN_LED_EVENT_RX;
8430 		} else if (rx == 0) {
8431 			evt = BWN_LED_EVENT_POLL;
8432 		}
8433 
8434 		if (evt != BWN_LED_EVENT_NONE)
8435 			bwn_led_event(mac, evt);
8436        }
8437 
8438 	if (mbufq_first(&sc->sc_snd) != NULL)
8439 		bwn_start(sc);
8440 
8441 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
8442 	BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
8443 
8444 	BWN_UNLOCK(sc);
8445 }
8446 
8447 static void
8448 bwn_restart(struct bwn_mac *mac, const char *msg)
8449 {
8450 	struct bwn_softc *sc = mac->mac_sc;
8451 	struct ieee80211com *ic = &sc->sc_ic;
8452 
8453 	if (mac->mac_status < BWN_MAC_STATUS_INITED)
8454 		return;
8455 
8456 	device_printf(sc->sc_dev, "HW reset: %s\n", msg);
8457 	ieee80211_runtask(ic, &mac->mac_hwreset);
8458 }
8459 
8460 static void
8461 bwn_intr_ucode_debug(struct bwn_mac *mac)
8462 {
8463 	struct bwn_softc *sc = mac->mac_sc;
8464 	uint16_t reason;
8465 
8466 	if (mac->mac_fw.opensource == 0)
8467 		return;
8468 
8469 	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG);
8470 	switch (reason) {
8471 	case BWN_DEBUGINTR_PANIC:
8472 		bwn_handle_fwpanic(mac);
8473 		break;
8474 	case BWN_DEBUGINTR_DUMP_SHM:
8475 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_SHM\n");
8476 		break;
8477 	case BWN_DEBUGINTR_DUMP_REGS:
8478 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_DUMP_REGS\n");
8479 		break;
8480 	case BWN_DEBUGINTR_MARKER:
8481 		device_printf(sc->sc_dev, "BWN_DEBUGINTR_MARKER\n");
8482 		break;
8483 	default:
8484 		device_printf(sc->sc_dev,
8485 		    "ucode debug unknown reason: %#x\n", reason);
8486 	}
8487 
8488 	bwn_shm_write_2(mac, BWN_SCRATCH, BWN_DEBUGINTR_REASON_REG,
8489 	    BWN_DEBUGINTR_ACK);
8490 }
8491 
8492 static void
8493 bwn_intr_tbtt_indication(struct bwn_mac *mac)
8494 {
8495 	struct bwn_softc *sc = mac->mac_sc;
8496 	struct ieee80211com *ic = &sc->sc_ic;
8497 
8498 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
8499 		bwn_psctl(mac, 0);
8500 	if (ic->ic_opmode == IEEE80211_M_IBSS)
8501 		mac->mac_flags |= BWN_MAC_FLAG_DFQVALID;
8502 }
8503 
8504 static void
8505 bwn_intr_atim_end(struct bwn_mac *mac)
8506 {
8507 
8508 	if (mac->mac_flags & BWN_MAC_FLAG_DFQVALID) {
8509 		BWN_WRITE_4(mac, BWN_MACCMD,
8510 		    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_DFQ_VALID);
8511 		mac->mac_flags &= ~BWN_MAC_FLAG_DFQVALID;
8512 	}
8513 }
8514 
8515 static void
8516 bwn_intr_beacon(struct bwn_mac *mac)
8517 {
8518 	struct bwn_softc *sc = mac->mac_sc;
8519 	struct ieee80211com *ic = &sc->sc_ic;
8520 	uint32_t cmd, beacon0, beacon1;
8521 
8522 	if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
8523 	    ic->ic_opmode == IEEE80211_M_MBSS)
8524 		return;
8525 
8526 	mac->mac_intr_mask &= ~BWN_INTR_BEACON;
8527 
8528 	cmd = BWN_READ_4(mac, BWN_MACCMD);
8529 	beacon0 = (cmd & BWN_MACCMD_BEACON0_VALID);
8530 	beacon1 = (cmd & BWN_MACCMD_BEACON1_VALID);
8531 
8532 	if (beacon0 && beacon1) {
8533 		BWN_WRITE_4(mac, BWN_INTR_REASON, BWN_INTR_BEACON);
8534 		mac->mac_intr_mask |= BWN_INTR_BEACON;
8535 		return;
8536 	}
8537 
8538 	if (sc->sc_flags & BWN_FLAG_NEED_BEACON_TP) {
8539 		sc->sc_flags &= ~BWN_FLAG_NEED_BEACON_TP;
8540 		bwn_load_beacon0(mac);
8541 		bwn_load_beacon1(mac);
8542 		cmd = BWN_READ_4(mac, BWN_MACCMD);
8543 		cmd |= BWN_MACCMD_BEACON0_VALID;
8544 		BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8545 	} else {
8546 		if (!beacon0) {
8547 			bwn_load_beacon0(mac);
8548 			cmd = BWN_READ_4(mac, BWN_MACCMD);
8549 			cmd |= BWN_MACCMD_BEACON0_VALID;
8550 			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8551 		} else if (!beacon1) {
8552 			bwn_load_beacon1(mac);
8553 			cmd = BWN_READ_4(mac, BWN_MACCMD);
8554 			cmd |= BWN_MACCMD_BEACON1_VALID;
8555 			BWN_WRITE_4(mac, BWN_MACCMD, cmd);
8556 		}
8557 	}
8558 }
8559 
8560 static void
8561 bwn_intr_pmq(struct bwn_mac *mac)
8562 {
8563 	uint32_t tmp;
8564 
8565 	while (1) {
8566 		tmp = BWN_READ_4(mac, BWN_PS_STATUS);
8567 		if (!(tmp & 0x00000008))
8568 			break;
8569 	}
8570 	BWN_WRITE_2(mac, BWN_PS_STATUS, 0x0002);
8571 }
8572 
8573 static void
8574 bwn_intr_noise(struct bwn_mac *mac)
8575 {
8576 	struct bwn_phy_g *pg = &mac->mac_phy.phy_g;
8577 	uint16_t tmp;
8578 	uint8_t noise[4];
8579 	uint8_t i, j;
8580 	int32_t average;
8581 
8582 	if (mac->mac_phy.type != BWN_PHYTYPE_G)
8583 		return;
8584 
8585 	KASSERT(mac->mac_noise.noi_running, ("%s: fail", __func__));
8586 	*((uint32_t *)noise) = htole32(bwn_jssi_read(mac));
8587 	if (noise[0] == 0x7f || noise[1] == 0x7f || noise[2] == 0x7f ||
8588 	    noise[3] == 0x7f)
8589 		goto new;
8590 
8591 	KASSERT(mac->mac_noise.noi_nsamples < 8,
8592 	    ("%s:%d: fail", __func__, __LINE__));
8593 	i = mac->mac_noise.noi_nsamples;
8594 	noise[0] = MIN(MAX(noise[0], 0), N(pg->pg_nrssi_lt) - 1);
8595 	noise[1] = MIN(MAX(noise[1], 0), N(pg->pg_nrssi_lt) - 1);
8596 	noise[2] = MIN(MAX(noise[2], 0), N(pg->pg_nrssi_lt) - 1);
8597 	noise[3] = MIN(MAX(noise[3], 0), N(pg->pg_nrssi_lt) - 1);
8598 	mac->mac_noise.noi_samples[i][0] = pg->pg_nrssi_lt[noise[0]];
8599 	mac->mac_noise.noi_samples[i][1] = pg->pg_nrssi_lt[noise[1]];
8600 	mac->mac_noise.noi_samples[i][2] = pg->pg_nrssi_lt[noise[2]];
8601 	mac->mac_noise.noi_samples[i][3] = pg->pg_nrssi_lt[noise[3]];
8602 	mac->mac_noise.noi_nsamples++;
8603 	if (mac->mac_noise.noi_nsamples == 8) {
8604 		average = 0;
8605 		for (i = 0; i < 8; i++) {
8606 			for (j = 0; j < 4; j++)
8607 				average += mac->mac_noise.noi_samples[i][j];
8608 		}
8609 		average = (((average / 32) * 125) + 64) / 128;
8610 		tmp = (bwn_shm_read_2(mac, BWN_SHARED, 0x40c) / 128) & 0x1f;
8611 		if (tmp >= 8)
8612 			average += 2;
8613 		else
8614 			average -= 25;
8615 		average -= (tmp == 8) ? 72 : 48;
8616 
8617 		mac->mac_stats.link_noise = average;
8618 		mac->mac_noise.noi_running = 0;
8619 		return;
8620 	}
8621 new:
8622 	bwn_noise_gensample(mac);
8623 }
8624 
8625 static int
8626 bwn_pio_rx(struct bwn_pio_rxqueue *prq)
8627 {
8628 	struct bwn_mac *mac = prq->prq_mac;
8629 	struct bwn_softc *sc = mac->mac_sc;
8630 	unsigned int i;
8631 
8632 	BWN_ASSERT_LOCKED(sc);
8633 
8634 	if (mac->mac_status < BWN_MAC_STATUS_STARTED)
8635 		return (0);
8636 
8637 	for (i = 0; i < 5000; i++) {
8638 		if (bwn_pio_rxeof(prq) == 0)
8639 			break;
8640 	}
8641 	if (i >= 5000)
8642 		device_printf(sc->sc_dev, "too many RX frames in PIO mode\n");
8643 	return ((i > 0) ? 1 : 0);
8644 }
8645 
8646 static void
8647 bwn_dma_rx(struct bwn_dma_ring *dr)
8648 {
8649 	int slot, curslot;
8650 
8651 	KASSERT(!dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
8652 	curslot = dr->get_curslot(dr);
8653 	KASSERT(curslot >= 0 && curslot < dr->dr_numslots,
8654 	    ("%s:%d: fail", __func__, __LINE__));
8655 
8656 	slot = dr->dr_curslot;
8657 	for (; slot != curslot; slot = bwn_dma_nextslot(dr, slot))
8658 		bwn_dma_rxeof(dr, &slot);
8659 
8660 	bus_dmamap_sync(dr->dr_ring_dtag, dr->dr_ring_dmap,
8661 	    BUS_DMASYNC_PREWRITE);
8662 
8663 	dr->set_curslot(dr, slot);
8664 	dr->dr_curslot = slot;
8665 }
8666 
8667 static void
8668 bwn_intr_txeof(struct bwn_mac *mac)
8669 {
8670 	struct bwn_txstatus stat;
8671 	uint32_t stat0, stat1;
8672 	uint16_t tmp;
8673 
8674 	BWN_ASSERT_LOCKED(mac->mac_sc);
8675 
8676 	while (1) {
8677 		stat0 = BWN_READ_4(mac, BWN_XMITSTAT_0);
8678 		if (!(stat0 & 0x00000001))
8679 			break;
8680 		stat1 = BWN_READ_4(mac, BWN_XMITSTAT_1);
8681 
8682 		stat.cookie = (stat0 >> 16);
8683 		stat.seq = (stat1 & 0x0000ffff);
8684 		stat.phy_stat = ((stat1 & 0x00ff0000) >> 16);
8685 		tmp = (stat0 & 0x0000ffff);
8686 		stat.framecnt = ((tmp & 0xf000) >> 12);
8687 		stat.rtscnt = ((tmp & 0x0f00) >> 8);
8688 		stat.sreason = ((tmp & 0x001c) >> 2);
8689 		stat.pm = (tmp & 0x0080) ? 1 : 0;
8690 		stat.im = (tmp & 0x0040) ? 1 : 0;
8691 		stat.ampdu = (tmp & 0x0020) ? 1 : 0;
8692 		stat.ack = (tmp & 0x0002) ? 1 : 0;
8693 
8694 		bwn_handle_txeof(mac, &stat);
8695 	}
8696 }
8697 
8698 static void
8699 bwn_hwreset(void *arg, int npending)
8700 {
8701 	struct bwn_mac *mac = arg;
8702 	struct bwn_softc *sc = mac->mac_sc;
8703 	int error = 0;
8704 	int prev_status;
8705 
8706 	BWN_LOCK(sc);
8707 
8708 	prev_status = mac->mac_status;
8709 	if (prev_status >= BWN_MAC_STATUS_STARTED)
8710 		bwn_core_stop(mac);
8711 	if (prev_status >= BWN_MAC_STATUS_INITED)
8712 		bwn_core_exit(mac);
8713 
8714 	if (prev_status >= BWN_MAC_STATUS_INITED) {
8715 		error = bwn_core_init(mac);
8716 		if (error)
8717 			goto out;
8718 	}
8719 	if (prev_status >= BWN_MAC_STATUS_STARTED)
8720 		bwn_core_start(mac);
8721 out:
8722 	if (error) {
8723 		device_printf(sc->sc_dev, "%s: failed (%d)\n", __func__, error);
8724 		sc->sc_curmac = NULL;
8725 	}
8726 	BWN_UNLOCK(sc);
8727 }
8728 
8729 static void
8730 bwn_handle_fwpanic(struct bwn_mac *mac)
8731 {
8732 	struct bwn_softc *sc = mac->mac_sc;
8733 	uint16_t reason;
8734 
8735 	reason = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_FWPANIC_REASON_REG);
8736 	device_printf(sc->sc_dev,"fw panic (%u)\n", reason);
8737 
8738 	if (reason == BWN_FWPANIC_RESTART)
8739 		bwn_restart(mac, "ucode panic");
8740 }
8741 
8742 static void
8743 bwn_load_beacon0(struct bwn_mac *mac)
8744 {
8745 
8746 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8747 }
8748 
8749 static void
8750 bwn_load_beacon1(struct bwn_mac *mac)
8751 {
8752 
8753 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
8754 }
8755 
8756 static uint32_t
8757 bwn_jssi_read(struct bwn_mac *mac)
8758 {
8759 	uint32_t val = 0;
8760 
8761 	val = bwn_shm_read_2(mac, BWN_SHARED, 0x08a);
8762 	val <<= 16;
8763 	val |= bwn_shm_read_2(mac, BWN_SHARED, 0x088);
8764 
8765 	return (val);
8766 }
8767 
8768 static void
8769 bwn_noise_gensample(struct bwn_mac *mac)
8770 {
8771 	uint32_t jssi = 0x7f7f7f7f;
8772 
8773 	bwn_shm_write_2(mac, BWN_SHARED, 0x088, (jssi & 0x0000ffff));
8774 	bwn_shm_write_2(mac, BWN_SHARED, 0x08a, (jssi & 0xffff0000) >> 16);
8775 	BWN_WRITE_4(mac, BWN_MACCMD,
8776 	    BWN_READ_4(mac, BWN_MACCMD) | BWN_MACCMD_BGNOISE);
8777 }
8778 
8779 static int
8780 bwn_dma_freeslot(struct bwn_dma_ring *dr)
8781 {
8782 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8783 
8784 	return (dr->dr_numslots - dr->dr_usedslot);
8785 }
8786 
8787 static int
8788 bwn_dma_nextslot(struct bwn_dma_ring *dr, int slot)
8789 {
8790 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
8791 
8792 	KASSERT(slot >= -1 && slot <= dr->dr_numslots - 1,
8793 	    ("%s:%d: fail", __func__, __LINE__));
8794 	if (slot == dr->dr_numslots - 1)
8795 		return (0);
8796 	return (slot + 1);
8797 }
8798 
8799 static void
8800 bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
8801 {
8802 	struct bwn_mac *mac = dr->dr_mac;
8803 	struct bwn_softc *sc = mac->mac_sc;
8804 	struct bwn_dma *dma = &mac->mac_method.dma;
8805 	struct bwn_dmadesc_generic *desc;
8806 	struct bwn_dmadesc_meta *meta;
8807 	struct bwn_rxhdr4 *rxhdr;
8808 	struct mbuf *m;
8809 	uint32_t macstat;
8810 	int32_t tmp;
8811 	int cnt = 0;
8812 	uint16_t len;
8813 
8814 	dr->getdesc(dr, *slot, &desc, &meta);
8815 
8816 	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap, BUS_DMASYNC_POSTREAD);
8817 	m = meta->mt_m;
8818 
8819 	if (bwn_dma_newbuf(dr, desc, meta, 0)) {
8820 		counter_u64_add(sc->sc_ic.ic_ierrors, 1);
8821 		return;
8822 	}
8823 
8824 	rxhdr = mtod(m, struct bwn_rxhdr4 *);
8825 	len = le16toh(rxhdr->frame_len);
8826 	if (len <= 0) {
8827 		counter_u64_add(sc->sc_ic.ic_ierrors, 1);
8828 		return;
8829 	}
8830 	if (bwn_dma_check_redzone(dr, m)) {
8831 		device_printf(sc->sc_dev, "redzone error.\n");
8832 		bwn_dma_set_redzone(dr, m);
8833 		bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8834 		    BUS_DMASYNC_PREWRITE);
8835 		return;
8836 	}
8837 	if (len > dr->dr_rx_bufsize) {
8838 		tmp = len;
8839 		while (1) {
8840 			dr->getdesc(dr, *slot, &desc, &meta);
8841 			bwn_dma_set_redzone(dr, meta->mt_m);
8842 			bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
8843 			    BUS_DMASYNC_PREWRITE);
8844 			*slot = bwn_dma_nextslot(dr, *slot);
8845 			cnt++;
8846 			tmp -= dr->dr_rx_bufsize;
8847 			if (tmp <= 0)
8848 				break;
8849 		}
8850 		device_printf(sc->sc_dev, "too small buffer "
8851 		       "(len %u buffer %u dropped %d)\n",
8852 		       len, dr->dr_rx_bufsize, cnt);
8853 		return;
8854 	}
8855 	macstat = le32toh(rxhdr->mac_status);
8856 	if (macstat & BWN_RX_MAC_FCSERR) {
8857 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
8858 			device_printf(sc->sc_dev, "RX drop\n");
8859 			return;
8860 		}
8861 	}
8862 
8863 	m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
8864 	m_adj(m, dr->dr_frameoffset);
8865 
8866 	bwn_rxeof(dr->dr_mac, m, rxhdr);
8867 }
8868 
8869 static void
8870 bwn_handle_txeof(struct bwn_mac *mac, const struct bwn_txstatus *status)
8871 {
8872 	struct bwn_dma_ring *dr;
8873 	struct bwn_dmadesc_generic *desc;
8874 	struct bwn_dmadesc_meta *meta;
8875 	struct bwn_pio_txqueue *tq;
8876 	struct bwn_pio_txpkt *tp = NULL;
8877 	struct bwn_softc *sc = mac->mac_sc;
8878 	struct bwn_stats *stats = &mac->mac_stats;
8879 	struct ieee80211_node *ni;
8880 	struct ieee80211vap *vap;
8881 	int retrycnt = 0, slot;
8882 
8883 	BWN_ASSERT_LOCKED(mac->mac_sc);
8884 
8885 	if (status->im)
8886 		device_printf(sc->sc_dev, "TODO: STATUS IM\n");
8887 	if (status->ampdu)
8888 		device_printf(sc->sc_dev, "TODO: STATUS AMPDU\n");
8889 	if (status->rtscnt) {
8890 		if (status->rtscnt == 0xf)
8891 			stats->rtsfail++;
8892 		else
8893 			stats->rts++;
8894 	}
8895 
8896 	if (mac->mac_flags & BWN_MAC_FLAG_DMA) {
8897 		if (status->ack) {
8898 			dr = bwn_dma_parse_cookie(mac, status,
8899 			    status->cookie, &slot);
8900 			if (dr == NULL) {
8901 				device_printf(sc->sc_dev,
8902 				    "failed to parse cookie\n");
8903 				return;
8904 			}
8905 			while (1) {
8906 				dr->getdesc(dr, slot, &desc, &meta);
8907 				if (meta->mt_islast) {
8908 					ni = meta->mt_ni;
8909 					vap = ni->ni_vap;
8910 					ieee80211_ratectl_tx_complete(vap, ni,
8911 					    status->ack ?
8912 					      IEEE80211_RATECTL_TX_SUCCESS :
8913 					      IEEE80211_RATECTL_TX_FAILURE,
8914 					    &retrycnt, 0);
8915 					break;
8916 				}
8917 				slot = bwn_dma_nextslot(dr, slot);
8918 			}
8919 		}
8920 		bwn_dma_handle_txeof(mac, status);
8921 	} else {
8922 		if (status->ack) {
8923 			tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
8924 			if (tq == NULL) {
8925 				device_printf(sc->sc_dev,
8926 				    "failed to parse cookie\n");
8927 				return;
8928 			}
8929 			ni = tp->tp_ni;
8930 			vap = ni->ni_vap;
8931 			ieee80211_ratectl_tx_complete(vap, ni,
8932 			    status->ack ?
8933 			      IEEE80211_RATECTL_TX_SUCCESS :
8934 			      IEEE80211_RATECTL_TX_FAILURE,
8935 			    &retrycnt, 0);
8936 		}
8937 		bwn_pio_handle_txeof(mac, status);
8938 	}
8939 
8940 	bwn_phy_txpower_check(mac, 0);
8941 }
8942 
8943 static uint8_t
8944 bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
8945 {
8946 	struct bwn_mac *mac = prq->prq_mac;
8947 	struct bwn_softc *sc = mac->mac_sc;
8948 	struct bwn_rxhdr4 rxhdr;
8949 	struct mbuf *m;
8950 	uint32_t ctl32, macstat, v32;
8951 	unsigned int i, padding;
8952 	uint16_t ctl16, len, totlen, v16;
8953 	unsigned char *mp;
8954 	char *data;
8955 
8956 	memset(&rxhdr, 0, sizeof(rxhdr));
8957 
8958 	if (prq->prq_rev >= 8) {
8959 		ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
8960 		if (!(ctl32 & BWN_PIO8_RXCTL_FRAMEREADY))
8961 			return (0);
8962 		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
8963 		    BWN_PIO8_RXCTL_FRAMEREADY);
8964 		for (i = 0; i < 10; i++) {
8965 			ctl32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXCTL);
8966 			if (ctl32 & BWN_PIO8_RXCTL_DATAREADY)
8967 				goto ready;
8968 			DELAY(10);
8969 		}
8970 	} else {
8971 		ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
8972 		if (!(ctl16 & BWN_PIO_RXCTL_FRAMEREADY))
8973 			return (0);
8974 		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL,
8975 		    BWN_PIO_RXCTL_FRAMEREADY);
8976 		for (i = 0; i < 10; i++) {
8977 			ctl16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXCTL);
8978 			if (ctl16 & BWN_PIO_RXCTL_DATAREADY)
8979 				goto ready;
8980 			DELAY(10);
8981 		}
8982 	}
8983 	device_printf(sc->sc_dev, "%s: timed out\n", __func__);
8984 	return (1);
8985 ready:
8986 	if (prq->prq_rev >= 8)
8987 		siba_read_multi_4(sc->sc_dev, &rxhdr, sizeof(rxhdr),
8988 		    prq->prq_base + BWN_PIO8_RXDATA);
8989 	else
8990 		siba_read_multi_2(sc->sc_dev, &rxhdr, sizeof(rxhdr),
8991 		    prq->prq_base + BWN_PIO_RXDATA);
8992 	len = le16toh(rxhdr.frame_len);
8993 	if (len > 0x700) {
8994 		device_printf(sc->sc_dev, "%s: len is too big\n", __func__);
8995 		goto error;
8996 	}
8997 	if (len == 0) {
8998 		device_printf(sc->sc_dev, "%s: len is 0\n", __func__);
8999 		goto error;
9000 	}
9001 
9002 	macstat = le32toh(rxhdr.mac_status);
9003 	if (macstat & BWN_RX_MAC_FCSERR) {
9004 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADFCS)) {
9005 			device_printf(sc->sc_dev, "%s: FCS error", __func__);
9006 			goto error;
9007 		}
9008 	}
9009 
9010 	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9011 	totlen = len + padding;
9012 	KASSERT(totlen <= MCLBYTES, ("too big..\n"));
9013 	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
9014 	if (m == NULL) {
9015 		device_printf(sc->sc_dev, "%s: out of memory", __func__);
9016 		goto error;
9017 	}
9018 	mp = mtod(m, unsigned char *);
9019 	if (prq->prq_rev >= 8) {
9020 		siba_read_multi_4(sc->sc_dev, mp, (totlen & ~3),
9021 		    prq->prq_base + BWN_PIO8_RXDATA);
9022 		if (totlen & 3) {
9023 			v32 = bwn_pio_rx_read_4(prq, BWN_PIO8_RXDATA);
9024 			data = &(mp[totlen - 1]);
9025 			switch (totlen & 3) {
9026 			case 3:
9027 				*data = (v32 >> 16);
9028 				data--;
9029 			case 2:
9030 				*data = (v32 >> 8);
9031 				data--;
9032 			case 1:
9033 				*data = v32;
9034 			}
9035 		}
9036 	} else {
9037 		siba_read_multi_2(sc->sc_dev, mp, (totlen & ~1),
9038 		    prq->prq_base + BWN_PIO_RXDATA);
9039 		if (totlen & 1) {
9040 			v16 = bwn_pio_rx_read_2(prq, BWN_PIO_RXDATA);
9041 			mp[totlen - 1] = v16;
9042 		}
9043 	}
9044 
9045 	m->m_len = m->m_pkthdr.len = totlen;
9046 
9047 	bwn_rxeof(prq->prq_mac, m, &rxhdr);
9048 
9049 	return (1);
9050 error:
9051 	if (prq->prq_rev >= 8)
9052 		bwn_pio_rx_write_4(prq, BWN_PIO8_RXCTL,
9053 		    BWN_PIO8_RXCTL_DATAREADY);
9054 	else
9055 		bwn_pio_rx_write_2(prq, BWN_PIO_RXCTL, BWN_PIO_RXCTL_DATAREADY);
9056 	return (1);
9057 }
9058 
9059 static int
9060 bwn_dma_newbuf(struct bwn_dma_ring *dr, struct bwn_dmadesc_generic *desc,
9061     struct bwn_dmadesc_meta *meta, int init)
9062 {
9063 	struct bwn_mac *mac = dr->dr_mac;
9064 	struct bwn_dma *dma = &mac->mac_method.dma;
9065 	struct bwn_rxhdr4 *hdr;
9066 	bus_dmamap_t map;
9067 	bus_addr_t paddr;
9068 	struct mbuf *m;
9069 	int error;
9070 
9071 	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
9072 	if (m == NULL) {
9073 		error = ENOBUFS;
9074 
9075 		/*
9076 		 * If the NIC is up and running, we need to:
9077 		 * - Clear RX buffer's header.
9078 		 * - Restore RX descriptor settings.
9079 		 */
9080 		if (init)
9081 			return (error);
9082 		else
9083 			goto back;
9084 	}
9085 	m->m_len = m->m_pkthdr.len = MCLBYTES;
9086 
9087 	bwn_dma_set_redzone(dr, m);
9088 
9089 	/*
9090 	 * Try to load RX buf into temporary DMA map
9091 	 */
9092 	error = bus_dmamap_load_mbuf(dma->rxbuf_dtag, dr->dr_spare_dmap, m,
9093 	    bwn_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
9094 	if (error) {
9095 		m_freem(m);
9096 
9097 		/*
9098 		 * See the comment above
9099 		 */
9100 		if (init)
9101 			return (error);
9102 		else
9103 			goto back;
9104 	}
9105 
9106 	if (!init)
9107 		bus_dmamap_unload(dma->rxbuf_dtag, meta->mt_dmap);
9108 	meta->mt_m = m;
9109 	meta->mt_paddr = paddr;
9110 
9111 	/*
9112 	 * Swap RX buf's DMA map with the loaded temporary one
9113 	 */
9114 	map = meta->mt_dmap;
9115 	meta->mt_dmap = dr->dr_spare_dmap;
9116 	dr->dr_spare_dmap = map;
9117 
9118 back:
9119 	/*
9120 	 * Clear RX buf header
9121 	 */
9122 	hdr = mtod(meta->mt_m, struct bwn_rxhdr4 *);
9123 	bzero(hdr, sizeof(*hdr));
9124 	bus_dmamap_sync(dma->rxbuf_dtag, meta->mt_dmap,
9125 	    BUS_DMASYNC_PREWRITE);
9126 
9127 	/*
9128 	 * Setup RX buf descriptor
9129 	 */
9130 	dr->setdesc(dr, desc, meta->mt_paddr, meta->mt_m->m_len -
9131 	    sizeof(*hdr), 0, 0, 0);
9132 	return (error);
9133 }
9134 
9135 static void
9136 bwn_dma_buf_addr(void *arg, bus_dma_segment_t *seg, int nseg,
9137 		 bus_size_t mapsz __unused, int error)
9138 {
9139 
9140 	if (!error) {
9141 		KASSERT(nseg == 1, ("too many segments(%d)\n", nseg));
9142 		*((bus_addr_t *)arg) = seg->ds_addr;
9143 	}
9144 }
9145 
9146 static int
9147 bwn_hwrate2ieeerate(int rate)
9148 {
9149 
9150 	switch (rate) {
9151 	case BWN_CCK_RATE_1MB:
9152 		return (2);
9153 	case BWN_CCK_RATE_2MB:
9154 		return (4);
9155 	case BWN_CCK_RATE_5MB:
9156 		return (11);
9157 	case BWN_CCK_RATE_11MB:
9158 		return (22);
9159 	case BWN_OFDM_RATE_6MB:
9160 		return (12);
9161 	case BWN_OFDM_RATE_9MB:
9162 		return (18);
9163 	case BWN_OFDM_RATE_12MB:
9164 		return (24);
9165 	case BWN_OFDM_RATE_18MB:
9166 		return (36);
9167 	case BWN_OFDM_RATE_24MB:
9168 		return (48);
9169 	case BWN_OFDM_RATE_36MB:
9170 		return (72);
9171 	case BWN_OFDM_RATE_48MB:
9172 		return (96);
9173 	case BWN_OFDM_RATE_54MB:
9174 		return (108);
9175 	default:
9176 		printf("Ooops\n");
9177 		return (0);
9178 	}
9179 }
9180 
9181 static void
9182 bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
9183 {
9184 	const struct bwn_rxhdr4 *rxhdr = _rxhdr;
9185 	struct bwn_plcp6 *plcp;
9186 	struct bwn_softc *sc = mac->mac_sc;
9187 	struct ieee80211_frame_min *wh;
9188 	struct ieee80211_node *ni;
9189 	struct ieee80211com *ic = &sc->sc_ic;
9190 	uint32_t macstat;
9191 	int padding, rate, rssi = 0, noise = 0, type;
9192 	uint16_t phytype, phystat0, phystat3, chanstat;
9193 	unsigned char *mp = mtod(m, unsigned char *);
9194 	static int rx_mac_dec_rpt = 0;
9195 
9196 	BWN_ASSERT_LOCKED(sc);
9197 
9198 	phystat0 = le16toh(rxhdr->phy_status0);
9199 	phystat3 = le16toh(rxhdr->phy_status3);
9200 	macstat = le32toh(rxhdr->mac_status);
9201 	chanstat = le16toh(rxhdr->channel);
9202 	phytype = chanstat & BWN_RX_CHAN_PHYTYPE;
9203 
9204 	if (macstat & BWN_RX_MAC_FCSERR)
9205 		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_FCS_CRC\n");
9206 	if (phystat0 & (BWN_RX_PHYST0_PLCPHCF | BWN_RX_PHYST0_PLCPFV))
9207 		device_printf(sc->sc_dev, "TODO RX: RX_FLAG_FAILED_PLCP_CRC\n");
9208 	if (macstat & BWN_RX_MAC_DECERR)
9209 		goto drop;
9210 
9211 	padding = (macstat & BWN_RX_MAC_PADDING) ? 2 : 0;
9212 	if (m->m_pkthdr.len < (sizeof(struct bwn_plcp6) + padding)) {
9213 		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9214 		    m->m_pkthdr.len);
9215 		goto drop;
9216 	}
9217 	plcp = (struct bwn_plcp6 *)(mp + padding);
9218 	m_adj(m, sizeof(struct bwn_plcp6) + padding);
9219 	if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
9220 		device_printf(sc->sc_dev, "frame too short (length=%d)\n",
9221 		    m->m_pkthdr.len);
9222 		goto drop;
9223 	}
9224 	wh = mtod(m, struct ieee80211_frame_min *);
9225 
9226 	if (macstat & BWN_RX_MAC_DEC && rx_mac_dec_rpt++ < 50)
9227 		device_printf(sc->sc_dev,
9228 		    "RX decryption attempted (old %d keyidx %#x)\n",
9229 		    BWN_ISOLDFMT(mac),
9230 		    (macstat & BWN_RX_MAC_KEYIDX) >> BWN_RX_MAC_KEYIDX_SHIFT);
9231 
9232 	/* XXX calculating RSSI & noise & antenna */
9233 
9234 	if (phystat0 & BWN_RX_PHYST0_OFDM)
9235 		rate = bwn_plcp_get_ofdmrate(mac, plcp,
9236 		    phytype == BWN_PHYTYPE_A);
9237 	else
9238 		rate = bwn_plcp_get_cckrate(mac, plcp);
9239 	if (rate == -1) {
9240 		if (!(mac->mac_sc->sc_filters & BWN_MACCTL_PASS_BADPLCP))
9241 			goto drop;
9242 	}
9243 	sc->sc_rx_rate = bwn_hwrate2ieeerate(rate);
9244 
9245 	/* RX radio tap */
9246 	if (ieee80211_radiotap_active(ic))
9247 		bwn_rx_radiotap(mac, m, rxhdr, plcp, rate, rssi, noise);
9248 	m_adj(m, -IEEE80211_CRC_LEN);
9249 
9250 	rssi = rxhdr->phy.abg.rssi;	/* XXX incorrect RSSI calculation? */
9251 	noise = mac->mac_stats.link_noise;
9252 
9253 	BWN_UNLOCK(sc);
9254 
9255 	ni = ieee80211_find_rxnode(ic, wh);
9256 	if (ni != NULL) {
9257 		type = ieee80211_input(ni, m, rssi, noise);
9258 		ieee80211_free_node(ni);
9259 	} else
9260 		type = ieee80211_input_all(ic, m, rssi, noise);
9261 
9262 	BWN_LOCK(sc);
9263 	return;
9264 drop:
9265 	device_printf(sc->sc_dev, "%s: dropped\n", __func__);
9266 }
9267 
9268 static void
9269 bwn_dma_handle_txeof(struct bwn_mac *mac,
9270     const struct bwn_txstatus *status)
9271 {
9272 	struct bwn_dma *dma = &mac->mac_method.dma;
9273 	struct bwn_dma_ring *dr;
9274 	struct bwn_dmadesc_generic *desc;
9275 	struct bwn_dmadesc_meta *meta;
9276 	struct bwn_softc *sc = mac->mac_sc;
9277 	int slot;
9278 
9279 	BWN_ASSERT_LOCKED(sc);
9280 
9281 	dr = bwn_dma_parse_cookie(mac, status, status->cookie, &slot);
9282 	if (dr == NULL) {
9283 		device_printf(sc->sc_dev, "failed to parse cookie\n");
9284 		return;
9285 	}
9286 	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9287 
9288 	while (1) {
9289 		KASSERT(slot >= 0 && slot < dr->dr_numslots,
9290 		    ("%s:%d: fail", __func__, __LINE__));
9291 		dr->getdesc(dr, slot, &desc, &meta);
9292 
9293 		if (meta->mt_txtype == BWN_DMADESC_METATYPE_HEADER)
9294 			bus_dmamap_unload(dr->dr_txring_dtag, meta->mt_dmap);
9295 		else if (meta->mt_txtype == BWN_DMADESC_METATYPE_BODY)
9296 			bus_dmamap_unload(dma->txbuf_dtag, meta->mt_dmap);
9297 
9298 		if (meta->mt_islast) {
9299 			KASSERT(meta->mt_m != NULL,
9300 			    ("%s:%d: fail", __func__, __LINE__));
9301 
9302 			ieee80211_tx_complete(meta->mt_ni, meta->mt_m, 0);
9303 			meta->mt_ni = NULL;
9304 			meta->mt_m = NULL;
9305 		} else
9306 			KASSERT(meta->mt_m == NULL,
9307 			    ("%s:%d: fail", __func__, __LINE__));
9308 
9309 		dr->dr_usedslot--;
9310 		if (meta->mt_islast)
9311 			break;
9312 		slot = bwn_dma_nextslot(dr, slot);
9313 	}
9314 	sc->sc_watchdog_timer = 0;
9315 	if (dr->dr_stop) {
9316 		KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
9317 		    ("%s:%d: fail", __func__, __LINE__));
9318 		dr->dr_stop = 0;
9319 	}
9320 }
9321 
9322 static void
9323 bwn_pio_handle_txeof(struct bwn_mac *mac,
9324     const struct bwn_txstatus *status)
9325 {
9326 	struct bwn_pio_txqueue *tq;
9327 	struct bwn_pio_txpkt *tp = NULL;
9328 	struct bwn_softc *sc = mac->mac_sc;
9329 
9330 	BWN_ASSERT_LOCKED(sc);
9331 
9332 	tq = bwn_pio_parse_cookie(mac, status->cookie, &tp);
9333 	if (tq == NULL)
9334 		return;
9335 
9336 	tq->tq_used -= roundup(tp->tp_m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
9337 	tq->tq_free++;
9338 
9339 	if (tp->tp_ni != NULL) {
9340 		/*
9341 		 * Do any tx complete callback.  Note this must
9342 		 * be done before releasing the node reference.
9343 		 */
9344 		if (tp->tp_m->m_flags & M_TXCB)
9345 			ieee80211_process_callback(tp->tp_ni, tp->tp_m, 0);
9346 		ieee80211_free_node(tp->tp_ni);
9347 		tp->tp_ni = NULL;
9348 	}
9349 	m_freem(tp->tp_m);
9350 	tp->tp_m = NULL;
9351 	TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
9352 
9353 	sc->sc_watchdog_timer = 0;
9354 }
9355 
9356 static void
9357 bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
9358 {
9359 	struct bwn_softc *sc = mac->mac_sc;
9360 	struct bwn_phy *phy = &mac->mac_phy;
9361 	struct ieee80211com *ic = &sc->sc_ic;
9362 	unsigned long now;
9363 	int result;
9364 
9365 	BWN_GETTIME(now);
9366 
9367 	if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
9368 		return;
9369 	phy->nexttime = now + 2 * 1000;
9370 
9371 	if (siba_get_pci_subvendor(sc->sc_dev) == SIBA_BOARDVENDOR_BCM &&
9372 	    siba_get_pci_subdevice(sc->sc_dev) == SIBA_BOARD_BU4306)
9373 		return;
9374 
9375 	if (phy->recalc_txpwr != NULL) {
9376 		result = phy->recalc_txpwr(mac,
9377 		    (flags & BWN_TXPWR_IGNORE_TSSI) ? 1 : 0);
9378 		if (result == BWN_TXPWR_RES_DONE)
9379 			return;
9380 		KASSERT(result == BWN_TXPWR_RES_NEED_ADJUST,
9381 		    ("%s: fail", __func__));
9382 		KASSERT(phy->set_txpwr != NULL, ("%s: fail", __func__));
9383 
9384 		ieee80211_runtask(ic, &mac->mac_txpower);
9385 	}
9386 }
9387 
9388 static uint16_t
9389 bwn_pio_rx_read_2(struct bwn_pio_rxqueue *prq, uint16_t offset)
9390 {
9391 
9392 	return (BWN_READ_2(prq->prq_mac, prq->prq_base + offset));
9393 }
9394 
9395 static uint32_t
9396 bwn_pio_rx_read_4(struct bwn_pio_rxqueue *prq, uint16_t offset)
9397 {
9398 
9399 	return (BWN_READ_4(prq->prq_mac, prq->prq_base + offset));
9400 }
9401 
9402 static void
9403 bwn_pio_rx_write_2(struct bwn_pio_rxqueue *prq, uint16_t offset, uint16_t value)
9404 {
9405 
9406 	BWN_WRITE_2(prq->prq_mac, prq->prq_base + offset, value);
9407 }
9408 
9409 static void
9410 bwn_pio_rx_write_4(struct bwn_pio_rxqueue *prq, uint16_t offset, uint32_t value)
9411 {
9412 
9413 	BWN_WRITE_4(prq->prq_mac, prq->prq_base + offset, value);
9414 }
9415 
9416 static int
9417 bwn_ieeerate2hwrate(struct bwn_softc *sc, int rate)
9418 {
9419 
9420 	switch (rate) {
9421 	/* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
9422 	case 12:
9423 		return (BWN_OFDM_RATE_6MB);
9424 	case 18:
9425 		return (BWN_OFDM_RATE_9MB);
9426 	case 24:
9427 		return (BWN_OFDM_RATE_12MB);
9428 	case 36:
9429 		return (BWN_OFDM_RATE_18MB);
9430 	case 48:
9431 		return (BWN_OFDM_RATE_24MB);
9432 	case 72:
9433 		return (BWN_OFDM_RATE_36MB);
9434 	case 96:
9435 		return (BWN_OFDM_RATE_48MB);
9436 	case 108:
9437 		return (BWN_OFDM_RATE_54MB);
9438 	/* CCK rates (NB: not IEEE std, device-specific) */
9439 	case 2:
9440 		return (BWN_CCK_RATE_1MB);
9441 	case 4:
9442 		return (BWN_CCK_RATE_2MB);
9443 	case 11:
9444 		return (BWN_CCK_RATE_5MB);
9445 	case 22:
9446 		return (BWN_CCK_RATE_11MB);
9447 	}
9448 
9449 	device_printf(sc->sc_dev, "unsupported rate %d\n", rate);
9450 	return (BWN_CCK_RATE_1MB);
9451 }
9452 
9453 static int
9454 bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
9455     struct mbuf *m, struct bwn_txhdr *txhdr, uint16_t cookie)
9456 {
9457 	const struct bwn_phy *phy = &mac->mac_phy;
9458 	struct bwn_softc *sc = mac->mac_sc;
9459 	struct ieee80211_frame *wh;
9460 	struct ieee80211_frame *protwh;
9461 	struct ieee80211_frame_cts *cts;
9462 	struct ieee80211_frame_rts *rts;
9463 	const struct ieee80211_txparam *tp;
9464 	struct ieee80211vap *vap = ni->ni_vap;
9465 	struct ieee80211com *ic = &sc->sc_ic;
9466 	struct mbuf *mprot;
9467 	unsigned int len;
9468 	uint32_t macctl = 0;
9469 	int protdur, rts_rate, rts_rate_fb, ismcast, isshort, rix, type;
9470 	uint16_t phyctl = 0;
9471 	uint8_t rate, rate_fb;
9472 
9473 	wh = mtod(m, struct ieee80211_frame *);
9474 	memset(txhdr, 0, sizeof(*txhdr));
9475 
9476 	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
9477 	ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1);
9478 	isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
9479 
9480 	/*
9481 	 * Find TX rate
9482 	 */
9483 	tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
9484 	if (type != IEEE80211_FC0_TYPE_DATA || (m->m_flags & M_EAPOL))
9485 		rate = rate_fb = tp->mgmtrate;
9486 	else if (ismcast)
9487 		rate = rate_fb = tp->mcastrate;
9488 	else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE)
9489 		rate = rate_fb = tp->ucastrate;
9490 	else {
9491 		rix = ieee80211_ratectl_rate(ni, NULL, 0);
9492 		rate = ni->ni_txrate;
9493 
9494 		if (rix > 0)
9495 			rate_fb = ni->ni_rates.rs_rates[rix - 1] &
9496 			    IEEE80211_RATE_VAL;
9497 		else
9498 			rate_fb = rate;
9499 	}
9500 
9501 	sc->sc_tx_rate = rate;
9502 
9503 	rate = bwn_ieeerate2hwrate(sc, rate);
9504 	rate_fb = bwn_ieeerate2hwrate(sc, rate_fb);
9505 
9506 	txhdr->phyrate = (BWN_ISOFDMRATE(rate)) ? bwn_plcp_getofdm(rate) :
9507 	    bwn_plcp_getcck(rate);
9508 	bcopy(wh->i_fc, txhdr->macfc, sizeof(txhdr->macfc));
9509 	bcopy(wh->i_addr1, txhdr->addr1, IEEE80211_ADDR_LEN);
9510 
9511 	if ((rate_fb == rate) ||
9512 	    (*(u_int16_t *)wh->i_dur & htole16(0x8000)) ||
9513 	    (*(u_int16_t *)wh->i_dur == htole16(0)))
9514 		txhdr->dur_fb = *(u_int16_t *)wh->i_dur;
9515 	else
9516 		txhdr->dur_fb = ieee80211_compute_duration(ic->ic_rt,
9517 		    m->m_pkthdr.len, rate, isshort);
9518 
9519 	/* XXX TX encryption */
9520 	bwn_plcp_genhdr(BWN_ISOLDFMT(mac) ?
9521 	    (struct bwn_plcp4 *)(&txhdr->body.old.plcp) :
9522 	    (struct bwn_plcp4 *)(&txhdr->body.new.plcp),
9523 	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate);
9524 	bwn_plcp_genhdr((struct bwn_plcp4 *)(&txhdr->plcp_fb),
9525 	    m->m_pkthdr.len + IEEE80211_CRC_LEN, rate_fb);
9526 
9527 	txhdr->eftypes |= (BWN_ISOFDMRATE(rate_fb)) ? BWN_TX_EFT_FB_OFDM :
9528 	    BWN_TX_EFT_FB_CCK;
9529 	txhdr->chan = phy->chan;
9530 	phyctl |= (BWN_ISOFDMRATE(rate)) ? BWN_TX_PHY_ENC_OFDM :
9531 	    BWN_TX_PHY_ENC_CCK;
9532 	if (isshort && (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9533 	     rate == BWN_CCK_RATE_11MB))
9534 		phyctl |= BWN_TX_PHY_SHORTPRMBL;
9535 
9536 	/* XXX TX antenna selection */
9537 
9538 	switch (bwn_antenna_sanitize(mac, 0)) {
9539 	case 0:
9540 		phyctl |= BWN_TX_PHY_ANT01AUTO;
9541 		break;
9542 	case 1:
9543 		phyctl |= BWN_TX_PHY_ANT0;
9544 		break;
9545 	case 2:
9546 		phyctl |= BWN_TX_PHY_ANT1;
9547 		break;
9548 	case 3:
9549 		phyctl |= BWN_TX_PHY_ANT2;
9550 		break;
9551 	case 4:
9552 		phyctl |= BWN_TX_PHY_ANT3;
9553 		break;
9554 	default:
9555 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9556 	}
9557 
9558 	if (!ismcast)
9559 		macctl |= BWN_TX_MAC_ACK;
9560 
9561 	macctl |= (BWN_TX_MAC_HWSEQ | BWN_TX_MAC_START_MSDU);
9562 	if (!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
9563 	    m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
9564 		macctl |= BWN_TX_MAC_LONGFRAME;
9565 
9566 	if (ic->ic_flags & IEEE80211_F_USEPROT) {
9567 		/* XXX RTS rate is always 1MB??? */
9568 		rts_rate = BWN_CCK_RATE_1MB;
9569 		rts_rate_fb = bwn_get_fbrate(rts_rate);
9570 
9571 		protdur = ieee80211_compute_duration(ic->ic_rt,
9572 		    m->m_pkthdr.len, rate, isshort) +
9573 		    + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
9574 
9575 		if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) {
9576 			cts = (struct ieee80211_frame_cts *)(BWN_ISOLDFMT(mac) ?
9577 			    (txhdr->body.old.rts_frame) :
9578 			    (txhdr->body.new.rts_frame));
9579 			mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr,
9580 			    protdur);
9581 			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9582 			bcopy(mtod(mprot, uint8_t *), (uint8_t *)cts,
9583 			    mprot->m_pkthdr.len);
9584 			m_freem(mprot);
9585 			macctl |= BWN_TX_MAC_SEND_CTSTOSELF;
9586 			len = sizeof(struct ieee80211_frame_cts);
9587 		} else {
9588 			rts = (struct ieee80211_frame_rts *)(BWN_ISOLDFMT(mac) ?
9589 			    (txhdr->body.old.rts_frame) :
9590 			    (txhdr->body.new.rts_frame));
9591 			protdur += ieee80211_ack_duration(ic->ic_rt, rate,
9592 			    isshort);
9593 			mprot = ieee80211_alloc_rts(ic, wh->i_addr1,
9594 			    wh->i_addr2, protdur);
9595 			KASSERT(mprot != NULL, ("failed to alloc mbuf\n"));
9596 			bcopy(mtod(mprot, uint8_t *), (uint8_t *)rts,
9597 			    mprot->m_pkthdr.len);
9598 			m_freem(mprot);
9599 			macctl |= BWN_TX_MAC_SEND_RTSCTS;
9600 			len = sizeof(struct ieee80211_frame_rts);
9601 		}
9602 		len += IEEE80211_CRC_LEN;
9603 		bwn_plcp_genhdr((struct bwn_plcp4 *)((BWN_ISOLDFMT(mac)) ?
9604 		    &txhdr->body.old.rts_plcp :
9605 		    &txhdr->body.new.rts_plcp), len, rts_rate);
9606 		bwn_plcp_genhdr((struct bwn_plcp4 *)&txhdr->rts_plcp_fb, len,
9607 		    rts_rate_fb);
9608 
9609 		protwh = (struct ieee80211_frame *)(BWN_ISOLDFMT(mac) ?
9610 		    (&txhdr->body.old.rts_frame) :
9611 		    (&txhdr->body.new.rts_frame));
9612 		txhdr->rts_dur_fb = *(u_int16_t *)protwh->i_dur;
9613 
9614 		if (BWN_ISOFDMRATE(rts_rate)) {
9615 			txhdr->eftypes |= BWN_TX_EFT_RTS_OFDM;
9616 			txhdr->phyrate_rts = bwn_plcp_getofdm(rts_rate);
9617 		} else {
9618 			txhdr->eftypes |= BWN_TX_EFT_RTS_CCK;
9619 			txhdr->phyrate_rts = bwn_plcp_getcck(rts_rate);
9620 		}
9621 		txhdr->eftypes |= (BWN_ISOFDMRATE(rts_rate_fb)) ?
9622 		    BWN_TX_EFT_RTS_FBOFDM : BWN_TX_EFT_RTS_FBCCK;
9623 	}
9624 
9625 	if (BWN_ISOLDFMT(mac))
9626 		txhdr->body.old.cookie = htole16(cookie);
9627 	else
9628 		txhdr->body.new.cookie = htole16(cookie);
9629 
9630 	txhdr->macctl = htole32(macctl);
9631 	txhdr->phyctl = htole16(phyctl);
9632 
9633 	/*
9634 	 * TX radio tap
9635 	 */
9636 	if (ieee80211_radiotap_active_vap(vap)) {
9637 		sc->sc_tx_th.wt_flags = 0;
9638 		if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
9639 			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
9640 		if (isshort &&
9641 		    (rate == BWN_CCK_RATE_2MB || rate == BWN_CCK_RATE_5MB ||
9642 		     rate == BWN_CCK_RATE_11MB))
9643 			sc->sc_tx_th.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
9644 		sc->sc_tx_th.wt_rate = rate;
9645 
9646 		ieee80211_radiotap_tx(vap, m);
9647 	}
9648 
9649 	return (0);
9650 }
9651 
9652 static void
9653 bwn_plcp_genhdr(struct bwn_plcp4 *plcp, const uint16_t octets,
9654     const uint8_t rate)
9655 {
9656 	uint32_t d, plen;
9657 	uint8_t *raw = plcp->o.raw;
9658 
9659 	if (BWN_ISOFDMRATE(rate)) {
9660 		d = bwn_plcp_getofdm(rate);
9661 		KASSERT(!(octets & 0xf000),
9662 		    ("%s:%d: fail", __func__, __LINE__));
9663 		d |= (octets << 5);
9664 		plcp->o.data = htole32(d);
9665 	} else {
9666 		plen = octets * 16 / rate;
9667 		if ((octets * 16 % rate) > 0) {
9668 			plen++;
9669 			if ((rate == BWN_CCK_RATE_11MB)
9670 			    && ((octets * 8 % 11) < 4)) {
9671 				raw[1] = 0x84;
9672 			} else
9673 				raw[1] = 0x04;
9674 		} else
9675 			raw[1] = 0x04;
9676 		plcp->o.data |= htole32(plen << 16);
9677 		raw[0] = bwn_plcp_getcck(rate);
9678 	}
9679 }
9680 
9681 static uint8_t
9682 bwn_antenna_sanitize(struct bwn_mac *mac, uint8_t n)
9683 {
9684 	struct bwn_softc *sc = mac->mac_sc;
9685 	uint8_t mask;
9686 
9687 	if (n == 0)
9688 		return (0);
9689 	if (mac->mac_phy.gmode)
9690 		mask = siba_sprom_get_ant_bg(sc->sc_dev);
9691 	else
9692 		mask = siba_sprom_get_ant_a(sc->sc_dev);
9693 	if (!(mask & (1 << (n - 1))))
9694 		return (0);
9695 	return (n);
9696 }
9697 
9698 static uint8_t
9699 bwn_get_fbrate(uint8_t bitrate)
9700 {
9701 	switch (bitrate) {
9702 	case BWN_CCK_RATE_1MB:
9703 		return (BWN_CCK_RATE_1MB);
9704 	case BWN_CCK_RATE_2MB:
9705 		return (BWN_CCK_RATE_1MB);
9706 	case BWN_CCK_RATE_5MB:
9707 		return (BWN_CCK_RATE_2MB);
9708 	case BWN_CCK_RATE_11MB:
9709 		return (BWN_CCK_RATE_5MB);
9710 	case BWN_OFDM_RATE_6MB:
9711 		return (BWN_CCK_RATE_5MB);
9712 	case BWN_OFDM_RATE_9MB:
9713 		return (BWN_OFDM_RATE_6MB);
9714 	case BWN_OFDM_RATE_12MB:
9715 		return (BWN_OFDM_RATE_9MB);
9716 	case BWN_OFDM_RATE_18MB:
9717 		return (BWN_OFDM_RATE_12MB);
9718 	case BWN_OFDM_RATE_24MB:
9719 		return (BWN_OFDM_RATE_18MB);
9720 	case BWN_OFDM_RATE_36MB:
9721 		return (BWN_OFDM_RATE_24MB);
9722 	case BWN_OFDM_RATE_48MB:
9723 		return (BWN_OFDM_RATE_36MB);
9724 	case BWN_OFDM_RATE_54MB:
9725 		return (BWN_OFDM_RATE_48MB);
9726 	}
9727 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9728 	return (0);
9729 }
9730 
9731 static uint32_t
9732 bwn_pio_write_multi_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9733     uint32_t ctl, const void *_data, int len)
9734 {
9735 	struct bwn_softc *sc = mac->mac_sc;
9736 	uint32_t value = 0;
9737 	const uint8_t *data = _data;
9738 
9739 	ctl |= BWN_PIO8_TXCTL_0_7 | BWN_PIO8_TXCTL_8_15 |
9740 	    BWN_PIO8_TXCTL_16_23 | BWN_PIO8_TXCTL_24_31;
9741 	bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9742 
9743 	siba_write_multi_4(sc->sc_dev, data, (len & ~3),
9744 	    tq->tq_base + BWN_PIO8_TXDATA);
9745 	if (len & 3) {
9746 		ctl &= ~(BWN_PIO8_TXCTL_8_15 | BWN_PIO8_TXCTL_16_23 |
9747 		    BWN_PIO8_TXCTL_24_31);
9748 		data = &(data[len - 1]);
9749 		switch (len & 3) {
9750 		case 3:
9751 			ctl |= BWN_PIO8_TXCTL_16_23;
9752 			value |= (uint32_t)(*data) << 16;
9753 			data--;
9754 		case 2:
9755 			ctl |= BWN_PIO8_TXCTL_8_15;
9756 			value |= (uint32_t)(*data) << 8;
9757 			data--;
9758 		case 1:
9759 			value |= (uint32_t)(*data);
9760 		}
9761 		bwn_pio_write_4(mac, tq, BWN_PIO8_TXCTL, ctl);
9762 		bwn_pio_write_4(mac, tq, BWN_PIO8_TXDATA, value);
9763 	}
9764 
9765 	return (ctl);
9766 }
9767 
9768 static void
9769 bwn_pio_write_4(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9770     uint16_t offset, uint32_t value)
9771 {
9772 
9773 	BWN_WRITE_4(mac, tq->tq_base + offset, value);
9774 }
9775 
9776 static uint16_t
9777 bwn_pio_write_multi_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9778     uint16_t ctl, const void *_data, int len)
9779 {
9780 	struct bwn_softc *sc = mac->mac_sc;
9781 	const uint8_t *data = _data;
9782 
9783 	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9784 	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9785 
9786 	siba_write_multi_2(sc->sc_dev, data, (len & ~1),
9787 	    tq->tq_base + BWN_PIO_TXDATA);
9788 	if (len & 1) {
9789 		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9790 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9791 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data[len - 1]);
9792 	}
9793 
9794 	return (ctl);
9795 }
9796 
9797 static uint16_t
9798 bwn_pio_write_mbuf_2(struct bwn_mac *mac, struct bwn_pio_txqueue *tq,
9799     uint16_t ctl, struct mbuf *m0)
9800 {
9801 	int i, j = 0;
9802 	uint16_t data = 0;
9803 	const uint8_t *buf;
9804 	struct mbuf *m = m0;
9805 
9806 	ctl |= BWN_PIO_TXCTL_WRITELO | BWN_PIO_TXCTL_WRITEHI;
9807 	BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9808 
9809 	for (; m != NULL; m = m->m_next) {
9810 		buf = mtod(m, const uint8_t *);
9811 		for (i = 0; i < m->m_len; i++) {
9812 			if (!((j++) % 2))
9813 				data |= buf[i];
9814 			else {
9815 				data |= (buf[i] << 8);
9816 				BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9817 				data = 0;
9818 			}
9819 		}
9820 	}
9821 	if (m0->m_pkthdr.len % 2) {
9822 		ctl &= ~BWN_PIO_TXCTL_WRITEHI;
9823 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXCTL, ctl);
9824 		BWN_PIO_WRITE_2(mac, tq, BWN_PIO_TXDATA, data);
9825 	}
9826 
9827 	return (ctl);
9828 }
9829 
9830 static void
9831 bwn_set_slot_time(struct bwn_mac *mac, uint16_t time)
9832 {
9833 
9834 	if (mac->mac_phy.type != BWN_PHYTYPE_G)
9835 		return;
9836 	BWN_WRITE_2(mac, 0x684, 510 + time);
9837 	bwn_shm_write_2(mac, BWN_SHARED, 0x0010, time);
9838 }
9839 
9840 static struct bwn_dma_ring *
9841 bwn_dma_select(struct bwn_mac *mac, uint8_t prio)
9842 {
9843 
9844 	if ((mac->mac_flags & BWN_MAC_FLAG_WME) == 0)
9845 		return (mac->mac_method.dma.wme[WME_AC_BE]);
9846 
9847 	switch (prio) {
9848 	case 3:
9849 		return (mac->mac_method.dma.wme[WME_AC_VO]);
9850 	case 2:
9851 		return (mac->mac_method.dma.wme[WME_AC_VI]);
9852 	case 0:
9853 		return (mac->mac_method.dma.wme[WME_AC_BE]);
9854 	case 1:
9855 		return (mac->mac_method.dma.wme[WME_AC_BK]);
9856 	}
9857 	KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
9858 	return (NULL);
9859 }
9860 
9861 static int
9862 bwn_dma_getslot(struct bwn_dma_ring *dr)
9863 {
9864 	int slot;
9865 
9866 	BWN_ASSERT_LOCKED(dr->dr_mac->mac_sc);
9867 
9868 	KASSERT(dr->dr_tx, ("%s:%d: fail", __func__, __LINE__));
9869 	KASSERT(!(dr->dr_stop), ("%s:%d: fail", __func__, __LINE__));
9870 	KASSERT(bwn_dma_freeslot(dr) != 0, ("%s:%d: fail", __func__, __LINE__));
9871 
9872 	slot = bwn_dma_nextslot(dr, dr->dr_curslot);
9873 	KASSERT(!(slot & ~0x0fff), ("%s:%d: fail", __func__, __LINE__));
9874 	dr->dr_curslot = slot;
9875 	dr->dr_usedslot++;
9876 
9877 	return (slot);
9878 }
9879 
9880 static int
9881 bwn_phy_shm_tssi_read(struct bwn_mac *mac, uint16_t shm_offset)
9882 {
9883 	const uint8_t ofdm = (shm_offset != BWN_SHARED_TSSI_CCK);
9884 	unsigned int a, b, c, d;
9885 	unsigned int avg;
9886 	uint32_t tmp;
9887 
9888 	tmp = bwn_shm_read_4(mac, BWN_SHARED, shm_offset);
9889 	a = tmp & 0xff;
9890 	b = (tmp >> 8) & 0xff;
9891 	c = (tmp >> 16) & 0xff;
9892 	d = (tmp >> 24) & 0xff;
9893 	if (a == 0 || a == BWN_TSSI_MAX || b == 0 || b == BWN_TSSI_MAX ||
9894 	    c == 0 || c == BWN_TSSI_MAX || d == 0 || d == BWN_TSSI_MAX)
9895 		return (ENOENT);
9896 	bwn_shm_write_4(mac, BWN_SHARED, shm_offset,
9897 	    BWN_TSSI_MAX | (BWN_TSSI_MAX << 8) |
9898 	    (BWN_TSSI_MAX << 16) | (BWN_TSSI_MAX << 24));
9899 
9900 	if (ofdm) {
9901 		a = (a + 32) & 0x3f;
9902 		b = (b + 32) & 0x3f;
9903 		c = (c + 32) & 0x3f;
9904 		d = (d + 32) & 0x3f;
9905 	}
9906 
9907 	avg = (a + b + c + d + 2) / 4;
9908 	if (ofdm) {
9909 		if (bwn_shm_read_2(mac, BWN_SHARED, BWN_SHARED_HFLO)
9910 		    & BWN_HF_4DB_CCK_POWERBOOST)
9911 			avg = (avg >= 13) ? (avg - 13) : 0;
9912 	}
9913 	return (avg);
9914 }
9915 
9916 static void
9917 bwn_phy_g_setatt(struct bwn_mac *mac, int *bbattp, int *rfattp)
9918 {
9919 	struct bwn_txpwr_loctl *lo = &mac->mac_phy.phy_g.pg_loctl;
9920 	int rfatt = *rfattp;
9921 	int bbatt = *bbattp;
9922 
9923 	while (1) {
9924 		if (rfatt > lo->rfatt.max && bbatt > lo->bbatt.max - 4)
9925 			break;
9926 		if (rfatt < lo->rfatt.min && bbatt < lo->bbatt.min + 4)
9927 			break;
9928 		if (bbatt > lo->bbatt.max && rfatt > lo->rfatt.max - 1)
9929 			break;
9930 		if (bbatt < lo->bbatt.min && rfatt < lo->rfatt.min + 1)
9931 			break;
9932 		if (bbatt > lo->bbatt.max) {
9933 			bbatt -= 4;
9934 			rfatt += 1;
9935 			continue;
9936 		}
9937 		if (bbatt < lo->bbatt.min) {
9938 			bbatt += 4;
9939 			rfatt -= 1;
9940 			continue;
9941 		}
9942 		if (rfatt > lo->rfatt.max) {
9943 			rfatt -= 1;
9944 			bbatt += 4;
9945 			continue;
9946 		}
9947 		if (rfatt < lo->rfatt.min) {
9948 			rfatt += 1;
9949 			bbatt -= 4;
9950 			continue;
9951 		}
9952 		break;
9953 	}
9954 
9955 	*rfattp = MIN(MAX(rfatt, lo->rfatt.min), lo->rfatt.max);
9956 	*bbattp = MIN(MAX(bbatt, lo->bbatt.min), lo->bbatt.max);
9957 }
9958 
9959 static void
9960 bwn_phy_lock(struct bwn_mac *mac)
9961 {
9962 	struct bwn_softc *sc = mac->mac_sc;
9963 	struct ieee80211com *ic = &sc->sc_ic;
9964 
9965 	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
9966 	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
9967 
9968 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
9969 		bwn_psctl(mac, BWN_PS_AWAKE);
9970 }
9971 
9972 static void
9973 bwn_phy_unlock(struct bwn_mac *mac)
9974 {
9975 	struct bwn_softc *sc = mac->mac_sc;
9976 	struct ieee80211com *ic = &sc->sc_ic;
9977 
9978 	KASSERT(siba_get_revid(sc->sc_dev) >= 3,
9979 	    ("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
9980 
9981 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
9982 		bwn_psctl(mac, 0);
9983 }
9984 
9985 static void
9986 bwn_rf_lock(struct bwn_mac *mac)
9987 {
9988 
9989 	BWN_WRITE_4(mac, BWN_MACCTL,
9990 	    BWN_READ_4(mac, BWN_MACCTL) | BWN_MACCTL_RADIO_LOCK);
9991 	BWN_READ_4(mac, BWN_MACCTL);
9992 	DELAY(10);
9993 }
9994 
9995 static void
9996 bwn_rf_unlock(struct bwn_mac *mac)
9997 {
9998 
9999 	BWN_READ_2(mac, BWN_PHYVER);
10000 	BWN_WRITE_4(mac, BWN_MACCTL,
10001 	    BWN_READ_4(mac, BWN_MACCTL) & ~BWN_MACCTL_RADIO_LOCK);
10002 }
10003 
10004 static struct bwn_pio_txqueue *
10005 bwn_pio_parse_cookie(struct bwn_mac *mac, uint16_t cookie,
10006     struct bwn_pio_txpkt **pack)
10007 {
10008 	struct bwn_pio *pio = &mac->mac_method.pio;
10009 	struct bwn_pio_txqueue *tq = NULL;
10010 	unsigned int index;
10011 
10012 	switch (cookie & 0xf000) {
10013 	case 0x1000:
10014 		tq = &pio->wme[WME_AC_BK];
10015 		break;
10016 	case 0x2000:
10017 		tq = &pio->wme[WME_AC_BE];
10018 		break;
10019 	case 0x3000:
10020 		tq = &pio->wme[WME_AC_VI];
10021 		break;
10022 	case 0x4000:
10023 		tq = &pio->wme[WME_AC_VO];
10024 		break;
10025 	case 0x5000:
10026 		tq = &pio->mcast;
10027 		break;
10028 	}
10029 	KASSERT(tq != NULL, ("%s:%d: fail", __func__, __LINE__));
10030 	if (tq == NULL)
10031 		return (NULL);
10032 	index = (cookie & 0x0fff);
10033 	KASSERT(index < N(tq->tq_pkts), ("%s:%d: fail", __func__, __LINE__));
10034 	if (index >= N(tq->tq_pkts))
10035 		return (NULL);
10036 	*pack = &tq->tq_pkts[index];
10037 	KASSERT(*pack != NULL, ("%s:%d: fail", __func__, __LINE__));
10038 	return (tq);
10039 }
10040 
10041 static void
10042 bwn_txpwr(void *arg, int npending)
10043 {
10044 	struct bwn_mac *mac = arg;
10045 	struct bwn_softc *sc = mac->mac_sc;
10046 
10047 	BWN_LOCK(sc);
10048 	if (mac && mac->mac_status >= BWN_MAC_STATUS_STARTED &&
10049 	    mac->mac_phy.set_txpwr != NULL)
10050 		mac->mac_phy.set_txpwr(mac);
10051 	BWN_UNLOCK(sc);
10052 }
10053 
10054 static void
10055 bwn_task_15s(struct bwn_mac *mac)
10056 {
10057 	uint16_t reg;
10058 
10059 	if (mac->mac_fw.opensource) {
10060 		reg = bwn_shm_read_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG);
10061 		if (reg) {
10062 			bwn_restart(mac, "fw watchdog");
10063 			return;
10064 		}
10065 		bwn_shm_write_2(mac, BWN_SCRATCH, BWN_WATCHDOG_REG, 1);
10066 	}
10067 	if (mac->mac_phy.task_15s)
10068 		mac->mac_phy.task_15s(mac);
10069 
10070 	mac->mac_phy.txerrors = BWN_TXERROR_MAX;
10071 }
10072 
10073 static void
10074 bwn_task_30s(struct bwn_mac *mac)
10075 {
10076 
10077 	if (mac->mac_phy.type != BWN_PHYTYPE_G || mac->mac_noise.noi_running)
10078 		return;
10079 	mac->mac_noise.noi_running = 1;
10080 	mac->mac_noise.noi_nsamples = 0;
10081 
10082 	bwn_noise_gensample(mac);
10083 }
10084 
10085 static void
10086 bwn_task_60s(struct bwn_mac *mac)
10087 {
10088 
10089 	if (mac->mac_phy.task_60s)
10090 		mac->mac_phy.task_60s(mac);
10091 	bwn_phy_txpower_check(mac, BWN_TXPWR_IGNORE_TIME);
10092 }
10093 
10094 static void
10095 bwn_tasks(void *arg)
10096 {
10097 	struct bwn_mac *mac = arg;
10098 	struct bwn_softc *sc = mac->mac_sc;
10099 
10100 	BWN_ASSERT_LOCKED(sc);
10101 	if (mac->mac_status != BWN_MAC_STATUS_STARTED)
10102 		return;
10103 
10104 	if (mac->mac_task_state % 4 == 0)
10105 		bwn_task_60s(mac);
10106 	if (mac->mac_task_state % 2 == 0)
10107 		bwn_task_30s(mac);
10108 	bwn_task_15s(mac);
10109 
10110 	mac->mac_task_state++;
10111 	callout_reset(&sc->sc_task_ch, hz * 15, bwn_tasks, mac);
10112 }
10113 
10114 static int
10115 bwn_plcp_get_ofdmrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp, uint8_t a)
10116 {
10117 	struct bwn_softc *sc = mac->mac_sc;
10118 
10119 	KASSERT(a == 0, ("not support APHY\n"));
10120 
10121 	switch (plcp->o.raw[0] & 0xf) {
10122 	case 0xb:
10123 		return (BWN_OFDM_RATE_6MB);
10124 	case 0xf:
10125 		return (BWN_OFDM_RATE_9MB);
10126 	case 0xa:
10127 		return (BWN_OFDM_RATE_12MB);
10128 	case 0xe:
10129 		return (BWN_OFDM_RATE_18MB);
10130 	case 0x9:
10131 		return (BWN_OFDM_RATE_24MB);
10132 	case 0xd:
10133 		return (BWN_OFDM_RATE_36MB);
10134 	case 0x8:
10135 		return (BWN_OFDM_RATE_48MB);
10136 	case 0xc:
10137 		return (BWN_OFDM_RATE_54MB);
10138 	}
10139 	device_printf(sc->sc_dev, "incorrect OFDM rate %d\n",
10140 	    plcp->o.raw[0] & 0xf);
10141 	return (-1);
10142 }
10143 
10144 static int
10145 bwn_plcp_get_cckrate(struct bwn_mac *mac, struct bwn_plcp6 *plcp)
10146 {
10147 	struct bwn_softc *sc = mac->mac_sc;
10148 
10149 	switch (plcp->o.raw[0]) {
10150 	case 0x0a:
10151 		return (BWN_CCK_RATE_1MB);
10152 	case 0x14:
10153 		return (BWN_CCK_RATE_2MB);
10154 	case 0x37:
10155 		return (BWN_CCK_RATE_5MB);
10156 	case 0x6e:
10157 		return (BWN_CCK_RATE_11MB);
10158 	}
10159 	device_printf(sc->sc_dev, "incorrect CCK rate %d\n", plcp->o.raw[0]);
10160 	return (-1);
10161 }
10162 
10163 static void
10164 bwn_rx_radiotap(struct bwn_mac *mac, struct mbuf *m,
10165     const struct bwn_rxhdr4 *rxhdr, struct bwn_plcp6 *plcp, int rate,
10166     int rssi, int noise)
10167 {
10168 	struct bwn_softc *sc = mac->mac_sc;
10169 	const struct ieee80211_frame_min *wh;
10170 	uint64_t tsf;
10171 	uint16_t low_mactime_now;
10172 
10173 	if (htole16(rxhdr->phy_status0) & BWN_RX_PHYST0_SHORTPRMBL)
10174 		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
10175 
10176 	wh = mtod(m, const struct ieee80211_frame_min *);
10177 	if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED)
10178 		sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_WEP;
10179 
10180 	bwn_tsf_read(mac, &tsf);
10181 	low_mactime_now = tsf;
10182 	tsf = tsf & ~0xffffULL;
10183 	tsf += le16toh(rxhdr->mac_time);
10184 	if (low_mactime_now < le16toh(rxhdr->mac_time))
10185 		tsf -= 0x10000;
10186 
10187 	sc->sc_rx_th.wr_tsf = tsf;
10188 	sc->sc_rx_th.wr_rate = rate;
10189 	sc->sc_rx_th.wr_antsignal = rssi;
10190 	sc->sc_rx_th.wr_antnoise = noise;
10191 }
10192 
10193 static void
10194 bwn_tsf_read(struct bwn_mac *mac, uint64_t *tsf)
10195 {
10196 	uint32_t low, high;
10197 
10198 	KASSERT(siba_get_revid(mac->mac_sc->sc_dev) >= 3,
10199 	    ("%s:%d: fail", __func__, __LINE__));
10200 
10201 	low = BWN_READ_4(mac, BWN_REV3PLUS_TSF_LOW);
10202 	high = BWN_READ_4(mac, BWN_REV3PLUS_TSF_HIGH);
10203 	*tsf = high;
10204 	*tsf <<= 32;
10205 	*tsf |= low;
10206 }
10207 
10208 static int
10209 bwn_dma_attach(struct bwn_mac *mac)
10210 {
10211 	struct bwn_dma *dma = &mac->mac_method.dma;
10212 	struct bwn_softc *sc = mac->mac_sc;
10213 	bus_addr_t lowaddr = 0;
10214 	int error;
10215 
10216 	if (siba_get_type(sc->sc_dev) == SIBA_TYPE_PCMCIA || bwn_usedma == 0)
10217 		return (0);
10218 
10219 	KASSERT(siba_get_revid(sc->sc_dev) >= 5, ("%s: fail", __func__));
10220 
10221 	mac->mac_flags |= BWN_MAC_FLAG_DMA;
10222 
10223 	dma->dmatype = bwn_dma_gettype(mac);
10224 	if (dma->dmatype == BWN_DMA_30BIT)
10225 		lowaddr = BWN_BUS_SPACE_MAXADDR_30BIT;
10226 	else if (dma->dmatype == BWN_DMA_32BIT)
10227 		lowaddr = BUS_SPACE_MAXADDR_32BIT;
10228 	else
10229 		lowaddr = BUS_SPACE_MAXADDR;
10230 
10231 	/*
10232 	 * Create top level DMA tag
10233 	 */
10234 	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),	/* parent */
10235 			       BWN_ALIGN, 0,		/* alignment, bounds */
10236 			       lowaddr,			/* lowaddr */
10237 			       BUS_SPACE_MAXADDR,	/* highaddr */
10238 			       NULL, NULL,		/* filter, filterarg */
10239 			       BUS_SPACE_MAXSIZE,	/* maxsize */
10240 			       BUS_SPACE_UNRESTRICTED,	/* nsegments */
10241 			       BUS_SPACE_MAXSIZE,	/* maxsegsize */
10242 			       0,			/* flags */
10243 			       NULL, NULL,		/* lockfunc, lockarg */
10244 			       &dma->parent_dtag);
10245 	if (error) {
10246 		device_printf(sc->sc_dev, "can't create parent DMA tag\n");
10247 		return (error);
10248 	}
10249 
10250 	/*
10251 	 * Create TX/RX mbuf DMA tag
10252 	 */
10253 	error = bus_dma_tag_create(dma->parent_dtag,
10254 				1,
10255 				0,
10256 				BUS_SPACE_MAXADDR,
10257 				BUS_SPACE_MAXADDR,
10258 				NULL, NULL,
10259 				MCLBYTES,
10260 				1,
10261 				BUS_SPACE_MAXSIZE_32BIT,
10262 				0,
10263 				NULL, NULL,
10264 				&dma->rxbuf_dtag);
10265 	if (error) {
10266 		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10267 		goto fail0;
10268 	}
10269 	error = bus_dma_tag_create(dma->parent_dtag,
10270 				1,
10271 				0,
10272 				BUS_SPACE_MAXADDR,
10273 				BUS_SPACE_MAXADDR,
10274 				NULL, NULL,
10275 				MCLBYTES,
10276 				1,
10277 				BUS_SPACE_MAXSIZE_32BIT,
10278 				0,
10279 				NULL, NULL,
10280 				&dma->txbuf_dtag);
10281 	if (error) {
10282 		device_printf(sc->sc_dev, "can't create mbuf DMA tag\n");
10283 		goto fail1;
10284 	}
10285 
10286 	dma->wme[WME_AC_BK] = bwn_dma_ringsetup(mac, 0, 1, dma->dmatype);
10287 	if (!dma->wme[WME_AC_BK])
10288 		goto fail2;
10289 
10290 	dma->wme[WME_AC_BE] = bwn_dma_ringsetup(mac, 1, 1, dma->dmatype);
10291 	if (!dma->wme[WME_AC_BE])
10292 		goto fail3;
10293 
10294 	dma->wme[WME_AC_VI] = bwn_dma_ringsetup(mac, 2, 1, dma->dmatype);
10295 	if (!dma->wme[WME_AC_VI])
10296 		goto fail4;
10297 
10298 	dma->wme[WME_AC_VO] = bwn_dma_ringsetup(mac, 3, 1, dma->dmatype);
10299 	if (!dma->wme[WME_AC_VO])
10300 		goto fail5;
10301 
10302 	dma->mcast = bwn_dma_ringsetup(mac, 4, 1, dma->dmatype);
10303 	if (!dma->mcast)
10304 		goto fail6;
10305 	dma->rx = bwn_dma_ringsetup(mac, 0, 0, dma->dmatype);
10306 	if (!dma->rx)
10307 		goto fail7;
10308 
10309 	return (error);
10310 
10311 fail7:	bwn_dma_ringfree(&dma->mcast);
10312 fail6:	bwn_dma_ringfree(&dma->wme[WME_AC_VO]);
10313 fail5:	bwn_dma_ringfree(&dma->wme[WME_AC_VI]);
10314 fail4:	bwn_dma_ringfree(&dma->wme[WME_AC_BE]);
10315 fail3:	bwn_dma_ringfree(&dma->wme[WME_AC_BK]);
10316 fail2:	bus_dma_tag_destroy(dma->txbuf_dtag);
10317 fail1:	bus_dma_tag_destroy(dma->rxbuf_dtag);
10318 fail0:	bus_dma_tag_destroy(dma->parent_dtag);
10319 	return (error);
10320 }
10321 
10322 static struct bwn_dma_ring *
10323 bwn_dma_parse_cookie(struct bwn_mac *mac, const struct bwn_txstatus *status,
10324     uint16_t cookie, int *slot)
10325 {
10326 	struct bwn_dma *dma = &mac->mac_method.dma;
10327 	struct bwn_dma_ring *dr;
10328 	struct bwn_softc *sc = mac->mac_sc;
10329 
10330 	BWN_ASSERT_LOCKED(mac->mac_sc);
10331 
10332 	switch (cookie & 0xf000) {
10333 	case 0x1000:
10334 		dr = dma->wme[WME_AC_BK];
10335 		break;
10336 	case 0x2000:
10337 		dr = dma->wme[WME_AC_BE];
10338 		break;
10339 	case 0x3000:
10340 		dr = dma->wme[WME_AC_VI];
10341 		break;
10342 	case 0x4000:
10343 		dr = dma->wme[WME_AC_VO];
10344 		break;
10345 	case 0x5000:
10346 		dr = dma->mcast;
10347 		break;
10348 	default:
10349 		dr = NULL;
10350 		KASSERT(0 == 1,
10351 		    ("invalid cookie value %d", cookie & 0xf000));
10352 	}
10353 	*slot = (cookie & 0x0fff);
10354 	if (*slot < 0 || *slot >= dr->dr_numslots) {
10355 		/*
10356 		 * XXX FIXME: sometimes H/W returns TX DONE events duplicately
10357 		 * that it occurs events which have same H/W sequence numbers.
10358 		 * When it's occurred just prints a WARNING msgs and ignores.
10359 		 */
10360 		KASSERT(status->seq == dma->lastseq,
10361 		    ("%s:%d: fail", __func__, __LINE__));
10362 		device_printf(sc->sc_dev,
10363 		    "out of slot ranges (0 < %d < %d)\n", *slot,
10364 		    dr->dr_numslots);
10365 		return (NULL);
10366 	}
10367 	dma->lastseq = status->seq;
10368 	return (dr);
10369 }
10370 
10371 static void
10372 bwn_dma_stop(struct bwn_mac *mac)
10373 {
10374 	struct bwn_dma *dma;
10375 
10376 	if ((mac->mac_flags & BWN_MAC_FLAG_DMA) == 0)
10377 		return;
10378 	dma = &mac->mac_method.dma;
10379 
10380 	bwn_dma_ringstop(&dma->rx);
10381 	bwn_dma_ringstop(&dma->wme[WME_AC_BK]);
10382 	bwn_dma_ringstop(&dma->wme[WME_AC_BE]);
10383 	bwn_dma_ringstop(&dma->wme[WME_AC_VI]);
10384 	bwn_dma_ringstop(&dma->wme[WME_AC_VO]);
10385 	bwn_dma_ringstop(&dma->mcast);
10386 }
10387 
10388 static void
10389 bwn_dma_ringstop(struct bwn_dma_ring **dr)
10390 {
10391 
10392 	if (dr == NULL)
10393 		return;
10394 
10395 	bwn_dma_cleanup(*dr);
10396 }
10397 
10398 static void
10399 bwn_pio_stop(struct bwn_mac *mac)
10400 {
10401 	struct bwn_pio *pio;
10402 
10403 	if (mac->mac_flags & BWN_MAC_FLAG_DMA)
10404 		return;
10405 	pio = &mac->mac_method.pio;
10406 
10407 	bwn_destroy_queue_tx(&pio->mcast);
10408 	bwn_destroy_queue_tx(&pio->wme[WME_AC_VO]);
10409 	bwn_destroy_queue_tx(&pio->wme[WME_AC_VI]);
10410 	bwn_destroy_queue_tx(&pio->wme[WME_AC_BE]);
10411 	bwn_destroy_queue_tx(&pio->wme[WME_AC_BK]);
10412 }
10413 
10414 static void
10415 bwn_led_attach(struct bwn_mac *mac)
10416 {
10417 	struct bwn_softc *sc = mac->mac_sc;
10418 	const uint8_t *led_act = NULL;
10419 	uint16_t val[BWN_LED_MAX];
10420 	int i;
10421 
10422 	sc->sc_led_idle = (2350 * hz) / 1000;
10423 	sc->sc_led_blink = 1;
10424 
10425 	for (i = 0; i < N(bwn_vendor_led_act); ++i) {
10426 		if (siba_get_pci_subvendor(sc->sc_dev) ==
10427 		    bwn_vendor_led_act[i].vid) {
10428 			led_act = bwn_vendor_led_act[i].led_act;
10429 			break;
10430 		}
10431 	}
10432 	if (led_act == NULL)
10433 		led_act = bwn_default_led_act;
10434 
10435 	val[0] = siba_sprom_get_gpio0(sc->sc_dev);
10436 	val[1] = siba_sprom_get_gpio1(sc->sc_dev);
10437 	val[2] = siba_sprom_get_gpio2(sc->sc_dev);
10438 	val[3] = siba_sprom_get_gpio3(sc->sc_dev);
10439 
10440 	for (i = 0; i < BWN_LED_MAX; ++i) {
10441 		struct bwn_led *led = &sc->sc_leds[i];
10442 
10443 		if (val[i] == 0xff) {
10444 			led->led_act = led_act[i];
10445 		} else {
10446 			if (val[i] & BWN_LED_ACT_LOW)
10447 				led->led_flags |= BWN_LED_F_ACTLOW;
10448 			led->led_act = val[i] & BWN_LED_ACT_MASK;
10449 		}
10450 		led->led_mask = (1 << i);
10451 
10452 		if (led->led_act == BWN_LED_ACT_BLINK_SLOW ||
10453 		    led->led_act == BWN_LED_ACT_BLINK_POLL ||
10454 		    led->led_act == BWN_LED_ACT_BLINK) {
10455 			led->led_flags |= BWN_LED_F_BLINK;
10456 			if (led->led_act == BWN_LED_ACT_BLINK_POLL)
10457 				led->led_flags |= BWN_LED_F_POLLABLE;
10458 			else if (led->led_act == BWN_LED_ACT_BLINK_SLOW)
10459 				led->led_flags |= BWN_LED_F_SLOW;
10460 
10461 			if (sc->sc_blink_led == NULL) {
10462 				sc->sc_blink_led = led;
10463 				if (led->led_flags & BWN_LED_F_SLOW)
10464 					BWN_LED_SLOWDOWN(sc->sc_led_idle);
10465 			}
10466 		}
10467 
10468 		DPRINTF(sc, BWN_DEBUG_LED,
10469 		    "%dth led, act %d, lowact %d\n", i,
10470 		    led->led_act, led->led_flags & BWN_LED_F_ACTLOW);
10471 	}
10472 	callout_init_mtx(&sc->sc_led_blink_ch, &sc->sc_mtx, 0);
10473 }
10474 
10475 static __inline uint16_t
10476 bwn_led_onoff(const struct bwn_led *led, uint16_t val, int on)
10477 {
10478 
10479 	if (led->led_flags & BWN_LED_F_ACTLOW)
10480 		on = !on;
10481 	if (on)
10482 		val |= led->led_mask;
10483 	else
10484 		val &= ~led->led_mask;
10485 	return val;
10486 }
10487 
10488 static void
10489 bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
10490 {
10491 	struct bwn_softc *sc = mac->mac_sc;
10492 	struct ieee80211com *ic = &sc->sc_ic;
10493 	uint16_t val;
10494 	int i;
10495 
10496 	if (nstate == IEEE80211_S_INIT) {
10497 		callout_stop(&sc->sc_led_blink_ch);
10498 		sc->sc_led_blinking = 0;
10499 	}
10500 
10501 	if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0)
10502 		return;
10503 
10504 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10505 	for (i = 0; i < BWN_LED_MAX; ++i) {
10506 		struct bwn_led *led = &sc->sc_leds[i];
10507 		int on;
10508 
10509 		if (led->led_act == BWN_LED_ACT_UNKN ||
10510 		    led->led_act == BWN_LED_ACT_NULL)
10511 			continue;
10512 
10513 		if ((led->led_flags & BWN_LED_F_BLINK) &&
10514 		    nstate != IEEE80211_S_INIT)
10515 			continue;
10516 
10517 		switch (led->led_act) {
10518 		case BWN_LED_ACT_ON:    /* Always on */
10519 			on = 1;
10520 			break;
10521 		case BWN_LED_ACT_OFF:   /* Always off */
10522 		case BWN_LED_ACT_5GHZ:  /* TODO: 11A */
10523 			on = 0;
10524 			break;
10525 		default:
10526 			on = 1;
10527 			switch (nstate) {
10528 			case IEEE80211_S_INIT:
10529 				on = 0;
10530 				break;
10531 			case IEEE80211_S_RUN:
10532 				if (led->led_act == BWN_LED_ACT_11G &&
10533 				    ic->ic_curmode != IEEE80211_MODE_11G)
10534 					on = 0;
10535 				break;
10536 			default:
10537 				if (led->led_act == BWN_LED_ACT_ASSOC)
10538 					on = 0;
10539 				break;
10540 			}
10541 			break;
10542 		}
10543 
10544 		val = bwn_led_onoff(led, val, on);
10545 	}
10546 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10547 }
10548 
10549 static void
10550 bwn_led_event(struct bwn_mac *mac, int event)
10551 {
10552 	struct bwn_softc *sc = mac->mac_sc;
10553 	struct bwn_led *led = sc->sc_blink_led;
10554 	int rate;
10555 
10556 	if (event == BWN_LED_EVENT_POLL) {
10557 		if ((led->led_flags & BWN_LED_F_POLLABLE) == 0)
10558 			return;
10559 		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
10560 			return;
10561 	}
10562 
10563 	sc->sc_led_ticks = ticks;
10564 	if (sc->sc_led_blinking)
10565 		return;
10566 
10567 	switch (event) {
10568 	case BWN_LED_EVENT_RX:
10569 		rate = sc->sc_rx_rate;
10570 		break;
10571 	case BWN_LED_EVENT_TX:
10572 		rate = sc->sc_tx_rate;
10573 		break;
10574 	case BWN_LED_EVENT_POLL:
10575 		rate = 0;
10576 		break;
10577 	default:
10578 		panic("unknown LED event %d\n", event);
10579 		break;
10580 	}
10581 	bwn_led_blink_start(mac, bwn_led_duration[rate].on_dur,
10582 	    bwn_led_duration[rate].off_dur);
10583 }
10584 
10585 static void
10586 bwn_led_blink_start(struct bwn_mac *mac, int on_dur, int off_dur)
10587 {
10588 	struct bwn_softc *sc = mac->mac_sc;
10589 	struct bwn_led *led = sc->sc_blink_led;
10590 	uint16_t val;
10591 
10592 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10593 	val = bwn_led_onoff(led, val, 1);
10594 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10595 
10596 	if (led->led_flags & BWN_LED_F_SLOW) {
10597 		BWN_LED_SLOWDOWN(on_dur);
10598 		BWN_LED_SLOWDOWN(off_dur);
10599 	}
10600 
10601 	sc->sc_led_blinking = 1;
10602 	sc->sc_led_blink_offdur = off_dur;
10603 
10604 	callout_reset(&sc->sc_led_blink_ch, on_dur, bwn_led_blink_next, mac);
10605 }
10606 
10607 static void
10608 bwn_led_blink_next(void *arg)
10609 {
10610 	struct bwn_mac *mac = arg;
10611 	struct bwn_softc *sc = mac->mac_sc;
10612 	uint16_t val;
10613 
10614 	val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
10615 	val = bwn_led_onoff(sc->sc_blink_led, val, 0);
10616 	BWN_WRITE_2(mac, BWN_GPIO_CONTROL, val);
10617 
10618 	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
10619 	    bwn_led_blink_end, mac);
10620 }
10621 
10622 static void
10623 bwn_led_blink_end(void *arg)
10624 {
10625 	struct bwn_mac *mac = arg;
10626 	struct bwn_softc *sc = mac->mac_sc;
10627 
10628 	sc->sc_led_blinking = 0;
10629 }
10630 
10631 static int
10632 bwn_suspend(device_t dev)
10633 {
10634 	struct bwn_softc *sc = device_get_softc(dev);
10635 
10636 	BWN_LOCK(sc);
10637 	bwn_stop(sc);
10638 	BWN_UNLOCK(sc);
10639 	return (0);
10640 }
10641 
10642 static int
10643 bwn_resume(device_t dev)
10644 {
10645 	struct bwn_softc *sc = device_get_softc(dev);
10646 	int error = EDOOFUS;
10647 
10648 	BWN_LOCK(sc);
10649 	if (sc->sc_ic.ic_nrunning > 0)
10650 		error = bwn_init(sc);
10651 	BWN_UNLOCK(sc);
10652 	if (error == 0)
10653 		ieee80211_start_all(&sc->sc_ic);
10654 	return (0);
10655 }
10656 
10657 static void
10658 bwn_rfswitch(void *arg)
10659 {
10660 	struct bwn_softc *sc = arg;
10661 	struct bwn_mac *mac = sc->sc_curmac;
10662 	int cur = 0, prev = 0;
10663 
10664 	KASSERT(mac->mac_status >= BWN_MAC_STATUS_STARTED,
10665 	    ("%s: invalid MAC status %d", __func__, mac->mac_status));
10666 
10667 	if (mac->mac_phy.rev >= 3 || mac->mac_phy.type == BWN_PHYTYPE_LP) {
10668 		if (!(BWN_READ_4(mac, BWN_RF_HWENABLED_HI)
10669 			& BWN_RF_HWENABLED_HI_MASK))
10670 			cur = 1;
10671 	} else {
10672 		if (BWN_READ_2(mac, BWN_RF_HWENABLED_LO)
10673 		    & BWN_RF_HWENABLED_LO_MASK)
10674 			cur = 1;
10675 	}
10676 
10677 	if (mac->mac_flags & BWN_MAC_FLAG_RADIO_ON)
10678 		prev = 1;
10679 
10680 	if (cur != prev) {
10681 		if (cur)
10682 			mac->mac_flags |= BWN_MAC_FLAG_RADIO_ON;
10683 		else
10684 			mac->mac_flags &= ~BWN_MAC_FLAG_RADIO_ON;
10685 
10686 		device_printf(sc->sc_dev,
10687 		    "status of RF switch is changed to %s\n",
10688 		    cur ? "ON" : "OFF");
10689 		if (cur != mac->mac_phy.rf_on) {
10690 			if (cur)
10691 				bwn_rf_turnon(mac);
10692 			else
10693 				bwn_rf_turnoff(mac);
10694 		}
10695 	}
10696 
10697 	callout_schedule(&sc->sc_rfswitch_ch, hz);
10698 }
10699 
10700 static void
10701 bwn_phy_lp_init_pre(struct bwn_mac *mac)
10702 {
10703 	struct bwn_phy *phy = &mac->mac_phy;
10704 	struct bwn_phy_lp *plp = &phy->phy_lp;
10705 
10706 	plp->plp_antenna = BWN_ANT_DEFAULT;
10707 }
10708 
10709 static int
10710 bwn_phy_lp_init(struct bwn_mac *mac)
10711 {
10712 	static const struct bwn_stxtable tables[] = {
10713 		{ 2,  6, 0x3d, 3, 0x01 }, { 1, 12, 0x4c, 1, 0x01 },
10714 		{ 1,  8, 0x50, 0, 0x7f }, { 0,  8, 0x44, 0, 0xff },
10715 		{ 1,  0, 0x4a, 0, 0xff }, { 0,  4, 0x4d, 0, 0xff },
10716 		{ 1,  4, 0x4e, 0, 0xff }, { 0, 12, 0x4f, 0, 0x0f },
10717 		{ 1,  0, 0x4f, 4, 0x0f }, { 3,  0, 0x49, 0, 0x0f },
10718 		{ 4,  3, 0x46, 4, 0x07 }, { 3, 15, 0x46, 0, 0x01 },
10719 		{ 4,  0, 0x46, 1, 0x07 }, { 3,  8, 0x48, 4, 0x07 },
10720 		{ 3, 11, 0x48, 0, 0x0f }, { 3,  4, 0x49, 4, 0x0f },
10721 		{ 2, 15, 0x45, 0, 0x01 }, { 5, 13, 0x52, 4, 0x07 },
10722 		{ 6,  0, 0x52, 7, 0x01 }, { 5,  3, 0x41, 5, 0x07 },
10723 		{ 5,  6, 0x41, 0, 0x0f }, { 5, 10, 0x42, 5, 0x07 },
10724 		{ 4, 15, 0x42, 0, 0x01 }, { 5,  0, 0x42, 1, 0x07 },
10725 		{ 4, 11, 0x43, 4, 0x0f }, { 4,  7, 0x43, 0, 0x0f },
10726 		{ 4,  6, 0x45, 1, 0x01 }, { 2,  7, 0x40, 4, 0x0f },
10727 		{ 2, 11, 0x40, 0, 0x0f }
10728 	};
10729 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10730 	struct bwn_softc *sc = mac->mac_sc;
10731 	const struct bwn_stxtable *st;
10732 	struct ieee80211com *ic = &sc->sc_ic;
10733 	int i, error;
10734 	uint16_t tmp;
10735 
10736 	bwn_phy_lp_readsprom(mac);	/* XXX bad place */
10737 	bwn_phy_lp_bbinit(mac);
10738 
10739 	/* initialize RF */
10740 	BWN_PHY_SET(mac, BWN_PHY_4WIRECTL, 0x2);
10741 	DELAY(1);
10742 	BWN_PHY_MASK(mac, BWN_PHY_4WIRECTL, 0xfffd);
10743 	DELAY(1);
10744 
10745 	if (mac->mac_phy.rf_ver == 0x2062)
10746 		bwn_phy_lp_b2062_init(mac);
10747 	else {
10748 		bwn_phy_lp_b2063_init(mac);
10749 
10750 		/* synchronize stx table. */
10751 		for (i = 0; i < N(tables); i++) {
10752 			st = &tables[i];
10753 			tmp = BWN_RF_READ(mac, st->st_rfaddr);
10754 			tmp >>= st->st_rfshift;
10755 			tmp <<= st->st_physhift;
10756 			BWN_PHY_SETMASK(mac,
10757 			    BWN_PHY_OFDM(0xf2 + st->st_phyoffset),
10758 			    ~(st->st_mask << st->st_physhift), tmp);
10759 		}
10760 
10761 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf0), 0x5f80);
10762 		BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xf1), 0);
10763 	}
10764 
10765 	/* calibrate RC */
10766 	if (mac->mac_phy.rev >= 2)
10767 		bwn_phy_lp_rxcal_r2(mac);
10768 	else if (!plp->plp_rccap) {
10769 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
10770 			bwn_phy_lp_rccal_r12(mac);
10771 	} else
10772 		bwn_phy_lp_set_rccap(mac);
10773 
10774 	error = bwn_phy_lp_switch_channel(mac, 7);
10775 	if (error)
10776 		device_printf(sc->sc_dev,
10777 		    "failed to change channel 7 (%d)\n", error);
10778 	bwn_phy_lp_txpctl_init(mac);
10779 	bwn_phy_lp_calib(mac);
10780 	return (0);
10781 }
10782 
10783 static uint16_t
10784 bwn_phy_lp_read(struct bwn_mac *mac, uint16_t reg)
10785 {
10786 
10787 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10788 	return (BWN_READ_2(mac, BWN_PHYDATA));
10789 }
10790 
10791 static void
10792 bwn_phy_lp_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10793 {
10794 
10795 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10796 	BWN_WRITE_2(mac, BWN_PHYDATA, value);
10797 }
10798 
10799 static void
10800 bwn_phy_lp_maskset(struct bwn_mac *mac, uint16_t reg, uint16_t mask,
10801     uint16_t set)
10802 {
10803 
10804 	BWN_WRITE_2(mac, BWN_PHYCTL, reg);
10805 	BWN_WRITE_2(mac, BWN_PHYDATA,
10806 	    (BWN_READ_2(mac, BWN_PHYDATA) & mask) | set);
10807 }
10808 
10809 static uint16_t
10810 bwn_phy_lp_rf_read(struct bwn_mac *mac, uint16_t reg)
10811 {
10812 
10813 	KASSERT(reg != 1, ("unaccessible register %d", reg));
10814 	if (mac->mac_phy.rev < 2 && reg != 0x4001)
10815 		reg |= 0x100;
10816 	if (mac->mac_phy.rev >= 2)
10817 		reg |= 0x200;
10818 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10819 	return BWN_READ_2(mac, BWN_RFDATALO);
10820 }
10821 
10822 static void
10823 bwn_phy_lp_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value)
10824 {
10825 
10826 	KASSERT(reg != 1, ("unaccessible register %d", reg));
10827 	BWN_WRITE_2(mac, BWN_RFCTL, reg);
10828 	BWN_WRITE_2(mac, BWN_RFDATALO, value);
10829 }
10830 
10831 static void
10832 bwn_phy_lp_rf_onoff(struct bwn_mac *mac, int on)
10833 {
10834 
10835 	if (on) {
10836 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xe0ff);
10837 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2,
10838 		    (mac->mac_phy.rev >= 2) ? 0xf7f7 : 0xffe7);
10839 		return;
10840 	}
10841 
10842 	if (mac->mac_phy.rev >= 2) {
10843 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x83ff);
10844 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10845 		BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0x80ff);
10846 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xdfff);
10847 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0808);
10848 		return;
10849 	}
10850 
10851 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xe0ff);
10852 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1f00);
10853 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfcff);
10854 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x0018);
10855 }
10856 
10857 static int
10858 bwn_phy_lp_switch_channel(struct bwn_mac *mac, uint32_t chan)
10859 {
10860 	struct bwn_phy *phy = &mac->mac_phy;
10861 	struct bwn_phy_lp *plp = &phy->phy_lp;
10862 	int error;
10863 
10864 	if (phy->rf_ver == 0x2063) {
10865 		error = bwn_phy_lp_b2063_switch_channel(mac, chan);
10866 		if (error)
10867 			return (error);
10868 	} else {
10869 		error = bwn_phy_lp_b2062_switch_channel(mac, chan);
10870 		if (error)
10871 			return (error);
10872 		bwn_phy_lp_set_anafilter(mac, chan);
10873 		bwn_phy_lp_set_gaintbl(mac, ieee80211_ieee2mhz(chan, 0));
10874 	}
10875 
10876 	plp->plp_chan = chan;
10877 	BWN_WRITE_2(mac, BWN_CHANNEL, chan);
10878 	return (0);
10879 }
10880 
10881 static uint32_t
10882 bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
10883 {
10884 	struct bwn_softc *sc = mac->mac_sc;
10885 	struct ieee80211com *ic = &sc->sc_ic;
10886 
10887 	return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
10888 }
10889 
10890 static void
10891 bwn_phy_lp_set_antenna(struct bwn_mac *mac, int antenna)
10892 {
10893 	struct bwn_phy *phy = &mac->mac_phy;
10894 	struct bwn_phy_lp *plp = &phy->phy_lp;
10895 
10896 	if (phy->rev >= 2 || antenna > BWN_ANTAUTO1)
10897 		return;
10898 
10899 	bwn_hf_write(mac, bwn_hf_read(mac) & ~BWN_HF_UCODE_ANTDIV_HELPER);
10900 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffd, antenna & 0x2);
10901 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfffe, antenna & 0x1);
10902 	bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_UCODE_ANTDIV_HELPER);
10903 	plp->plp_antenna = antenna;
10904 }
10905 
10906 static void
10907 bwn_phy_lp_task_60s(struct bwn_mac *mac)
10908 {
10909 
10910 	bwn_phy_lp_calib(mac);
10911 }
10912 
10913 static void
10914 bwn_phy_lp_readsprom(struct bwn_mac *mac)
10915 {
10916 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10917 	struct bwn_softc *sc = mac->mac_sc;
10918 	struct ieee80211com *ic = &sc->sc_ic;
10919 
10920 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
10921 		plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
10922 		plp->plp_bxarch = siba_sprom_get_bxa2g(sc->sc_dev);
10923 		plp->plp_rxpwroffset = siba_sprom_get_rxpo2g(sc->sc_dev);
10924 		plp->plp_rssivf = siba_sprom_get_rssismf2g(sc->sc_dev);
10925 		plp->plp_rssivc = siba_sprom_get_rssismc2g(sc->sc_dev);
10926 		plp->plp_rssigs = siba_sprom_get_rssisav2g(sc->sc_dev);
10927 		return;
10928 	}
10929 
10930 	plp->plp_txisoband_l = siba_sprom_get_tri5gl(sc->sc_dev);
10931 	plp->plp_txisoband_m = siba_sprom_get_tri5g(sc->sc_dev);
10932 	plp->plp_txisoband_h = siba_sprom_get_tri5gh(sc->sc_dev);
10933 	plp->plp_bxarch = siba_sprom_get_bxa5g(sc->sc_dev);
10934 	plp->plp_rxpwroffset = siba_sprom_get_rxpo5g(sc->sc_dev);
10935 	plp->plp_rssivf = siba_sprom_get_rssismf5g(sc->sc_dev);
10936 	plp->plp_rssivc = siba_sprom_get_rssismc5g(sc->sc_dev);
10937 	plp->plp_rssigs = siba_sprom_get_rssisav5g(sc->sc_dev);
10938 }
10939 
10940 static void
10941 bwn_phy_lp_bbinit(struct bwn_mac *mac)
10942 {
10943 
10944 	bwn_phy_lp_tblinit(mac);
10945 	if (mac->mac_phy.rev >= 2)
10946 		bwn_phy_lp_bbinit_r2(mac);
10947 	else
10948 		bwn_phy_lp_bbinit_r01(mac);
10949 }
10950 
10951 static void
10952 bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
10953 {
10954 	struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
10955 	struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
10956 	struct bwn_softc *sc = mac->mac_sc;
10957 	struct ieee80211com *ic = &sc->sc_ic;
10958 
10959 	bwn_phy_lp_set_txgain(mac,
10960 	    IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
10961 	bwn_phy_lp_set_bbmult(mac, 150);
10962 }
10963 
10964 static void
10965 bwn_phy_lp_calib(struct bwn_mac *mac)
10966 {
10967 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
10968 	struct bwn_softc *sc = mac->mac_sc;
10969 	struct ieee80211com *ic = &sc->sc_ic;
10970 	const struct bwn_rxcompco *rc = NULL;
10971 	struct bwn_txgain ogain;
10972 	int i, omode, oafeovr, orf, obbmult;
10973 	uint8_t mode, fc = 0;
10974 
10975 	if (plp->plp_chanfullcal != plp->plp_chan) {
10976 		plp->plp_chanfullcal = plp->plp_chan;
10977 		fc = 1;
10978 	}
10979 
10980 	bwn_mac_suspend(mac);
10981 
10982 	/* BlueTooth Coexistance Override */
10983 	BWN_WRITE_2(mac, BWN_BTCOEX_CTL, 0x3);
10984 	BWN_WRITE_2(mac, BWN_BTCOEX_TXCTL, 0xff);
10985 
10986 	if (mac->mac_phy.rev >= 2)
10987 		bwn_phy_lp_digflt_save(mac);
10988 	bwn_phy_lp_get_txpctlmode(mac);
10989 	mode = plp->plp_txpctlmode;
10990 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
10991 	if (mac->mac_phy.rev == 0 && mode != BWN_PHYLP_TXPCTL_OFF)
10992 		bwn_phy_lp_bugfix(mac);
10993 	if (mac->mac_phy.rev >= 2 && fc == 1) {
10994 		bwn_phy_lp_get_txpctlmode(mac);
10995 		omode = plp->plp_txpctlmode;
10996 		oafeovr = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40;
10997 		if (oafeovr)
10998 			ogain = bwn_phy_lp_get_txgain(mac);
10999 		orf = BWN_PHY_READ(mac, BWN_PHY_RF_PWR_OVERRIDE) & 0xff;
11000 		obbmult = bwn_phy_lp_get_bbmult(mac);
11001 		bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11002 		if (oafeovr)
11003 			bwn_phy_lp_set_txgain(mac, &ogain);
11004 		bwn_phy_lp_set_bbmult(mac, obbmult);
11005 		bwn_phy_lp_set_txpctlmode(mac, omode);
11006 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00, orf);
11007 	}
11008 	bwn_phy_lp_set_txpctlmode(mac, mode);
11009 	if (mac->mac_phy.rev >= 2)
11010 		bwn_phy_lp_digflt_restore(mac);
11011 
11012 	/* do RX IQ Calculation; assumes that noise is true. */
11013 	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
11014 		for (i = 0; i < N(bwn_rxcompco_5354); i++) {
11015 			if (bwn_rxcompco_5354[i].rc_chan == plp->plp_chan)
11016 				rc = &bwn_rxcompco_5354[i];
11017 		}
11018 	} else if (mac->mac_phy.rev >= 2)
11019 		rc = &bwn_rxcompco_r2;
11020 	else {
11021 		for (i = 0; i < N(bwn_rxcompco_r12); i++) {
11022 			if (bwn_rxcompco_r12[i].rc_chan == plp->plp_chan)
11023 				rc = &bwn_rxcompco_r12[i];
11024 		}
11025 	}
11026 	if (rc == NULL)
11027 		goto fail;
11028 
11029 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, rc->rc_c1);
11030 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, rc->rc_c0 << 8);
11031 
11032 	bwn_phy_lp_set_trsw_over(mac, 1 /* TX */, 0 /* RX */);
11033 
11034 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11035 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
11036 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7, 0);
11037 	} else {
11038 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
11039 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf, 0);
11040 	}
11041 
11042 	bwn_phy_lp_set_rxgain(mac, 0x2d5d);
11043 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11044 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
11045 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
11046 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
11047 	bwn_phy_lp_set_deaf(mac, 0);
11048 	/* XXX no checking return value? */
11049 	(void)bwn_phy_lp_calc_rx_iq_comp(mac, 0xfff0);
11050 	bwn_phy_lp_clear_deaf(mac, 0);
11051 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffc);
11052 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfff7);
11053 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffdf);
11054 
11055 	/* disable RX GAIN override. */
11056 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xfffe);
11057 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffef);
11058 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xffbf);
11059 	if (mac->mac_phy.rev >= 2) {
11060 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11061 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11062 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfbff);
11063 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xe5), 0xfff7);
11064 		}
11065 	} else {
11066 		BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfdff);
11067 	}
11068 
11069 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfffe);
11070 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xf7ff);
11071 fail:
11072 	bwn_mac_enable(mac);
11073 }
11074 
11075 static void
11076 bwn_phy_lp_switch_analog(struct bwn_mac *mac, int on)
11077 {
11078 
11079 	if (on) {
11080 		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xfff8);
11081 		return;
11082 	}
11083 
11084 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVRVAL, 0x0007);
11085 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x0007);
11086 }
11087 
11088 static int
11089 bwn_phy_lp_b2063_switch_channel(struct bwn_mac *mac, uint8_t chan)
11090 {
11091 	static const struct bwn_b206x_chan *bc = NULL;
11092 	struct bwn_softc *sc = mac->mac_sc;
11093 	uint32_t count, freqref, freqvco, freqxtal, val[3], timeout, timeoutref,
11094 	    tmp[6];
11095 	uint16_t old, scale, tmp16;
11096 	int i, div;
11097 
11098 	for (i = 0; i < N(bwn_b2063_chantable); i++) {
11099 		if (bwn_b2063_chantable[i].bc_chan == chan) {
11100 			bc = &bwn_b2063_chantable[i];
11101 			break;
11102 		}
11103 	}
11104 	if (bc == NULL)
11105 		return (EINVAL);
11106 
11107 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_VCOBUF1, bc->bc_data[0]);
11108 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_MIXER2, bc->bc_data[1]);
11109 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_BUF2, bc->bc_data[2]);
11110 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_RCCR1, bc->bc_data[3]);
11111 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_1ST3, bc->bc_data[4]);
11112 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND1, bc->bc_data[5]);
11113 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND4, bc->bc_data[6]);
11114 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_2ND7, bc->bc_data[7]);
11115 	BWN_RF_WRITE(mac, BWN_B2063_A_RX_PS6, bc->bc_data[8]);
11116 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL2, bc->bc_data[9]);
11117 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_CTL5, bc->bc_data[10]);
11118 	BWN_RF_WRITE(mac, BWN_B2063_PA_CTL11, bc->bc_data[11]);
11119 
11120 	old = BWN_RF_READ(mac, BWN_B2063_COM15);
11121 	BWN_RF_SET(mac, BWN_B2063_COM15, 0x1e);
11122 
11123 	freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11124 	freqvco = bc->bc_freq << ((bc->bc_freq > 4000) ? 1 : 2);
11125 	freqref = freqxtal * 3;
11126 	div = (freqxtal <= 26000000 ? 1 : 2);
11127 	timeout = ((((8 * freqxtal) / (div * 5000000)) + 1) >> 1) - 1;
11128 	timeoutref = ((((8 * freqxtal) / (div * (timeout + 1))) +
11129 		999999) / 1000000) + 1;
11130 
11131 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB3, 0x2);
11132 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB6,
11133 	    0xfff8, timeout >> 2);
11134 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11135 	    0xff9f,timeout << 5);
11136 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB5, timeoutref);
11137 
11138 	val[0] = bwn_phy_lp_roundup(freqxtal, 1000000, 16);
11139 	val[1] = bwn_phy_lp_roundup(freqxtal, 1000000 * div, 16);
11140 	val[2] = bwn_phy_lp_roundup(freqvco, 3, 16);
11141 
11142 	count = (bwn_phy_lp_roundup(val[2], val[1] + 16, 16) * (timeout + 1) *
11143 	    (timeoutref + 1)) - 1;
11144 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_VCO_CALIB7,
11145 	    0xf0, count >> 8);
11146 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_VCO_CALIB8, count & 0xff);
11147 
11148 	tmp[0] = ((val[2] * 62500) / freqref) << 4;
11149 	tmp[1] = ((val[2] * 62500) % freqref) << 4;
11150 	while (tmp[1] >= freqref) {
11151 		tmp[0]++;
11152 		tmp[1] -= freqref;
11153 	}
11154 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG1, 0xffe0, tmp[0] >> 4);
11155 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfe0f, tmp[0] << 4);
11156 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_SG2, 0xfff0, tmp[0] >> 16);
11157 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG3, (tmp[1] >> 8) & 0xff);
11158 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_SG4, tmp[1] & 0xff);
11159 
11160 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF1, 0xb9);
11161 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF2, 0x88);
11162 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF3, 0x28);
11163 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_LF4, 0x63);
11164 
11165 	tmp[2] = ((41 * (val[2] - 3000)) /1200) + 27;
11166 	tmp[3] = bwn_phy_lp_roundup(132000 * tmp[0], 8451, 16);
11167 
11168 	if ((tmp[3] + tmp[2] - 1) / tmp[2] > 60) {
11169 		scale = 1;
11170 		tmp[4] = ((tmp[3] + tmp[2]) / (tmp[2] << 1)) - 8;
11171 	} else {
11172 		scale = 0;
11173 		tmp[4] = ((tmp[3] + (tmp[2] >> 1)) / tmp[2]) - 8;
11174 	}
11175 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffc0, tmp[4]);
11176 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP2, 0xffbf, scale << 6);
11177 
11178 	tmp[5] = bwn_phy_lp_roundup(100 * val[0], val[2], 16) * (tmp[4] * 8) *
11179 	    (scale + 1);
11180 	if (tmp[5] > 150)
11181 		tmp[5] = 0;
11182 
11183 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffe0, tmp[5]);
11184 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_CP3, 0xffdf, scale << 5);
11185 
11186 	BWN_RF_SETMASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfffb, 0x4);
11187 	if (freqxtal > 26000000)
11188 		BWN_RF_SET(mac, BWN_B2063_JTAG_XTAL_12, 0x2);
11189 	else
11190 		BWN_RF_MASK(mac, BWN_B2063_JTAG_XTAL_12, 0xfd);
11191 
11192 	if (val[0] == 45)
11193 		BWN_RF_SET(mac, BWN_B2063_JTAG_VCO1, 0x2);
11194 	else
11195 		BWN_RF_MASK(mac, BWN_B2063_JTAG_VCO1, 0xfd);
11196 
11197 	BWN_RF_SET(mac, BWN_B2063_PLL_SP2, 0x3);
11198 	DELAY(1);
11199 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP2, 0xfffc);
11200 
11201 	/* VCO Calibration */
11202 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, ~0x40);
11203 	tmp16 = BWN_RF_READ(mac, BWN_B2063_JTAG_CALNRST) & 0xf8;
11204 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16);
11205 	DELAY(1);
11206 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x4);
11207 	DELAY(1);
11208 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x6);
11209 	DELAY(1);
11210 	BWN_RF_WRITE(mac, BWN_B2063_JTAG_CALNRST, tmp16 | 0x7);
11211 	DELAY(300);
11212 	BWN_RF_SET(mac, BWN_B2063_PLL_SP1, 0x40);
11213 
11214 	BWN_RF_WRITE(mac, BWN_B2063_COM15, old);
11215 	return (0);
11216 }
11217 
11218 static int
11219 bwn_phy_lp_b2062_switch_channel(struct bwn_mac *mac, uint8_t chan)
11220 {
11221 	struct bwn_softc *sc = mac->mac_sc;
11222 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11223 	const struct bwn_b206x_chan *bc = NULL;
11224 	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11225 	uint32_t tmp[9];
11226 	int i;
11227 
11228 	for (i = 0; i < N(bwn_b2062_chantable); i++) {
11229 		if (bwn_b2062_chantable[i].bc_chan == chan) {
11230 			bc = &bwn_b2062_chantable[i];
11231 			break;
11232 		}
11233 	}
11234 
11235 	if (bc == NULL)
11236 		return (EINVAL);
11237 
11238 	BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL14, 0x04);
11239 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE0, bc->bc_data[0]);
11240 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE2, bc->bc_data[1]);
11241 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENATUNE3, bc->bc_data[2]);
11242 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_TUNE, bc->bc_data[3]);
11243 	BWN_RF_WRITE(mac, BWN_B2062_S_LGENG_CTL1, bc->bc_data[4]);
11244 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL5, bc->bc_data[5]);
11245 	BWN_RF_WRITE(mac, BWN_B2062_N_LGENACTL6, bc->bc_data[6]);
11246 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PGA, bc->bc_data[7]);
11247 	BWN_RF_WRITE(mac, BWN_B2062_N_TX_PAD, bc->bc_data[8]);
11248 
11249 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xcc);
11250 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0x07);
11251 	bwn_phy_lp_b2062_reset_pllbias(mac);
11252 	tmp[0] = freqxtal / 1000;
11253 	tmp[1] = plp->plp_div * 1000;
11254 	tmp[2] = tmp[1] * ieee80211_ieee2mhz(chan, 0);
11255 	if (ieee80211_ieee2mhz(chan, 0) < 4000)
11256 		tmp[2] *= 2;
11257 	tmp[3] = 48 * tmp[0];
11258 	tmp[5] = tmp[2] / tmp[3];
11259 	tmp[6] = tmp[2] % tmp[3];
11260 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL26, tmp[5]);
11261 	tmp[4] = tmp[6] * 0x100;
11262 	tmp[5] = tmp[4] / tmp[3];
11263 	tmp[6] = tmp[4] % tmp[3];
11264 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL27, tmp[5]);
11265 	tmp[4] = tmp[6] * 0x100;
11266 	tmp[5] = tmp[4] / tmp[3];
11267 	tmp[6] = tmp[4] % tmp[3];
11268 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL28, tmp[5]);
11269 	tmp[4] = tmp[6] * 0x100;
11270 	tmp[5] = tmp[4] / tmp[3];
11271 	tmp[6] = tmp[4] % tmp[3];
11272 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL29,
11273 	    tmp[5] + ((2 * tmp[6]) / tmp[3]));
11274 	tmp[7] = BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL19);
11275 	tmp[8] = ((2 * tmp[2] * (tmp[7] + 1)) + (3 * tmp[0])) / (6 * tmp[0]);
11276 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL23, (tmp[8] >> 8) + 16);
11277 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL24, tmp[8] & 0xff);
11278 
11279 	bwn_phy_lp_b2062_vco_calib(mac);
11280 	if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11281 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL33, 0xfc);
11282 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL34, 0);
11283 		bwn_phy_lp_b2062_reset_pllbias(mac);
11284 		bwn_phy_lp_b2062_vco_calib(mac);
11285 		if (BWN_RF_READ(mac, BWN_B2062_S_RFPLLCTL3) & 0x10) {
11286 			BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11287 			return (EIO);
11288 		}
11289 	}
11290 	BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL14, ~0x04);
11291 	return (0);
11292 }
11293 
11294 static void
11295 bwn_phy_lp_set_anafilter(struct bwn_mac *mac, uint8_t channel)
11296 {
11297 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11298 	uint16_t tmp = (channel == 14);
11299 
11300 	if (mac->mac_phy.rev < 2) {
11301 		BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xfcff, tmp << 9);
11302 		if ((mac->mac_phy.rev == 1) && (plp->plp_rccap))
11303 			bwn_phy_lp_set_rccap(mac);
11304 		return;
11305 	}
11306 
11307 	BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, 0x3f);
11308 }
11309 
11310 static void
11311 bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
11312 {
11313 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11314 	struct bwn_softc *sc = mac->mac_sc;
11315 	struct ieee80211com *ic = &sc->sc_ic;
11316 	uint16_t iso, tmp[3];
11317 
11318 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
11319 
11320 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11321 		iso = plp->plp_txisoband_m;
11322 	else if (freq <= 5320)
11323 		iso = plp->plp_txisoband_l;
11324 	else if (freq <= 5700)
11325 		iso = plp->plp_txisoband_m;
11326 	else
11327 		iso = plp->plp_txisoband_h;
11328 
11329 	tmp[0] = ((iso - 26) / 12) << 12;
11330 	tmp[1] = tmp[0] + 0x1000;
11331 	tmp[2] = tmp[0] + 0x2000;
11332 
11333 	bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), 3, tmp);
11334 	bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), 3, tmp);
11335 }
11336 
11337 static void
11338 bwn_phy_lp_digflt_save(struct bwn_mac *mac)
11339 {
11340 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11341 	int i;
11342 	static const uint16_t addr[] = {
11343 		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11344 		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11345 		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11346 		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11347 		BWN_PHY_OFDM(0xcf),
11348 	};
11349 	static const uint16_t val[] = {
11350 		0xde5e, 0xe832, 0xe331, 0x4d26,
11351 		0x0026, 0x1420, 0x0020, 0xfe08,
11352 		0x0008,
11353 	};
11354 
11355 	for (i = 0; i < N(addr); i++) {
11356 		plp->plp_digfilt[i] = BWN_PHY_READ(mac, addr[i]);
11357 		BWN_PHY_WRITE(mac, addr[i], val[i]);
11358 	}
11359 }
11360 
11361 static void
11362 bwn_phy_lp_get_txpctlmode(struct bwn_mac *mac)
11363 {
11364 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11365 	struct bwn_softc *sc = mac->mac_sc;
11366 	uint16_t ctl;
11367 
11368 	ctl = BWN_PHY_READ(mac, BWN_PHY_TX_PWR_CTL_CMD);
11369 	switch (ctl & BWN_PHY_TX_PWR_CTL_CMD_MODE) {
11370 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF:
11371 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_OFF;
11372 		break;
11373 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_SW:
11374 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_SW;
11375 		break;
11376 	case BWN_PHY_TX_PWR_CTL_CMD_MODE_HW:
11377 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_ON_HW;
11378 		break;
11379 	default:
11380 		plp->plp_txpctlmode = BWN_PHYLP_TXPCTL_UNKNOWN;
11381 		device_printf(sc->sc_dev, "unknown command mode\n");
11382 		break;
11383 	}
11384 }
11385 
11386 static void
11387 bwn_phy_lp_set_txpctlmode(struct bwn_mac *mac, uint8_t mode)
11388 {
11389 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11390 	uint16_t ctl;
11391 	uint8_t old;
11392 
11393 	bwn_phy_lp_get_txpctlmode(mac);
11394 	old = plp->plp_txpctlmode;
11395 	if (old == mode)
11396 		return;
11397 	plp->plp_txpctlmode = mode;
11398 
11399 	if (old != BWN_PHYLP_TXPCTL_ON_HW && mode == BWN_PHYLP_TXPCTL_ON_HW) {
11400 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD, 0xff80,
11401 		    plp->plp_tssiidx);
11402 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_NNUM,
11403 		    0x8fff, ((uint16_t)plp->plp_tssinpt << 16));
11404 
11405 		/* disable TX GAIN override */
11406 		if (mac->mac_phy.rev < 2)
11407 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfeff);
11408 		else {
11409 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xff7f);
11410 			BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xbfff);
11411 		}
11412 		BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVR, 0xffbf);
11413 
11414 		plp->plp_txpwridx = -1;
11415 	}
11416 	if (mac->mac_phy.rev >= 2) {
11417 		if (mode == BWN_PHYLP_TXPCTL_ON_HW)
11418 			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xd0), 0x2);
11419 		else
11420 			BWN_PHY_MASK(mac, BWN_PHY_OFDM(0xd0), 0xfffd);
11421 	}
11422 
11423 	/* writes TX Power Control mode */
11424 	switch (plp->plp_txpctlmode) {
11425 	case BWN_PHYLP_TXPCTL_OFF:
11426 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_OFF;
11427 		break;
11428 	case BWN_PHYLP_TXPCTL_ON_HW:
11429 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_HW;
11430 		break;
11431 	case BWN_PHYLP_TXPCTL_ON_SW:
11432 		ctl = BWN_PHY_TX_PWR_CTL_CMD_MODE_SW;
11433 		break;
11434 	default:
11435 		ctl = 0;
11436 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
11437 	}
11438 	BWN_PHY_SETMASK(mac, BWN_PHY_TX_PWR_CTL_CMD,
11439 	    (uint16_t)~BWN_PHY_TX_PWR_CTL_CMD_MODE, ctl);
11440 }
11441 
11442 static void
11443 bwn_phy_lp_bugfix(struct bwn_mac *mac)
11444 {
11445 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11446 	struct bwn_softc *sc = mac->mac_sc;
11447 	const unsigned int size = 256;
11448 	struct bwn_txgain tg;
11449 	uint32_t rxcomp, txgain, coeff, rfpwr, *tabs;
11450 	uint16_t tssinpt, tssiidx, value[2];
11451 	uint8_t mode;
11452 	int8_t txpwridx;
11453 
11454 	tabs = (uint32_t *)malloc(sizeof(uint32_t) * size, M_DEVBUF,
11455 	    M_NOWAIT | M_ZERO);
11456 	if (tabs == NULL) {
11457 		device_printf(sc->sc_dev, "failed to allocate buffer.\n");
11458 		return;
11459 	}
11460 
11461 	bwn_phy_lp_get_txpctlmode(mac);
11462 	mode = plp->plp_txpctlmode;
11463 	txpwridx = plp->plp_txpwridx;
11464 	tssinpt = plp->plp_tssinpt;
11465 	tssiidx = plp->plp_tssiidx;
11466 
11467 	bwn_tab_read_multi(mac,
11468 	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11469 	    BWN_TAB_4(7, 0x140), size, tabs);
11470 
11471 	bwn_phy_lp_tblinit(mac);
11472 	bwn_phy_lp_bbinit(mac);
11473 	bwn_phy_lp_txpctl_init(mac);
11474 	bwn_phy_lp_rf_onoff(mac, 1);
11475 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
11476 
11477 	bwn_tab_write_multi(mac,
11478 	    (mac->mac_phy.rev < 2) ? BWN_TAB_4(10, 0x140) :
11479 	    BWN_TAB_4(7, 0x140), size, tabs);
11480 
11481 	BWN_WRITE_2(mac, BWN_CHANNEL, plp->plp_chan);
11482 	plp->plp_tssinpt = tssinpt;
11483 	plp->plp_tssiidx = tssiidx;
11484 	bwn_phy_lp_set_anafilter(mac, plp->plp_chan);
11485 	if (txpwridx != -1) {
11486 		/* set TX power by index */
11487 		plp->plp_txpwridx = txpwridx;
11488 		bwn_phy_lp_get_txpctlmode(mac);
11489 		if (plp->plp_txpctlmode != BWN_PHYLP_TXPCTL_OFF)
11490 			bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_ON_SW);
11491 		if (mac->mac_phy.rev >= 2) {
11492 			rxcomp = bwn_tab_read(mac,
11493 			    BWN_TAB_4(7, txpwridx + 320));
11494 			txgain = bwn_tab_read(mac,
11495 			    BWN_TAB_4(7, txpwridx + 192));
11496 			tg.tg_pad = (txgain >> 16) & 0xff;
11497 			tg.tg_gm = txgain & 0xff;
11498 			tg.tg_pga = (txgain >> 8) & 0xff;
11499 			tg.tg_dac = (rxcomp >> 28) & 0xff;
11500 			bwn_phy_lp_set_txgain(mac, &tg);
11501 		} else {
11502 			rxcomp = bwn_tab_read(mac,
11503 			    BWN_TAB_4(10, txpwridx + 320));
11504 			txgain = bwn_tab_read(mac,
11505 			    BWN_TAB_4(10, txpwridx + 192));
11506 			BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
11507 			    0xf800, (txgain >> 4) & 0x7fff);
11508 			bwn_phy_lp_set_txgain_dac(mac, txgain & 0x7);
11509 			bwn_phy_lp_set_txgain_pa(mac, (txgain >> 24) & 0x7f);
11510 		}
11511 		bwn_phy_lp_set_bbmult(mac, (rxcomp >> 20) & 0xff);
11512 
11513 		/* set TX IQCC */
11514 		value[0] = (rxcomp >> 10) & 0x3ff;
11515 		value[1] = rxcomp & 0x3ff;
11516 		bwn_tab_write_multi(mac, BWN_TAB_2(0, 80), 2, value);
11517 
11518 		coeff = bwn_tab_read(mac,
11519 		    (mac->mac_phy.rev >= 2) ? BWN_TAB_4(7, txpwridx + 448) :
11520 		    BWN_TAB_4(10, txpwridx + 448));
11521 		bwn_tab_write(mac, BWN_TAB_2(0, 85), coeff & 0xffff);
11522 		if (mac->mac_phy.rev >= 2) {
11523 			rfpwr = bwn_tab_read(mac,
11524 			    BWN_TAB_4(7, txpwridx + 576));
11525 			BWN_PHY_SETMASK(mac, BWN_PHY_RF_PWR_OVERRIDE, 0xff00,
11526 			    rfpwr & 0xffff);
11527 		}
11528 		bwn_phy_lp_set_txgain_override(mac);
11529 	}
11530 	if (plp->plp_rccap)
11531 		bwn_phy_lp_set_rccap(mac);
11532 	bwn_phy_lp_set_antenna(mac, plp->plp_antenna);
11533 	bwn_phy_lp_set_txpctlmode(mac, mode);
11534 	free(tabs, M_DEVBUF);
11535 }
11536 
11537 static void
11538 bwn_phy_lp_digflt_restore(struct bwn_mac *mac)
11539 {
11540 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11541 	int i;
11542 	static const uint16_t addr[] = {
11543 		BWN_PHY_OFDM(0xc1), BWN_PHY_OFDM(0xc2),
11544 		BWN_PHY_OFDM(0xc3), BWN_PHY_OFDM(0xc4),
11545 		BWN_PHY_OFDM(0xc5), BWN_PHY_OFDM(0xc6),
11546 		BWN_PHY_OFDM(0xc7), BWN_PHY_OFDM(0xc8),
11547 		BWN_PHY_OFDM(0xcf),
11548 	};
11549 
11550 	for (i = 0; i < N(addr); i++)
11551 		BWN_PHY_WRITE(mac, addr[i], plp->plp_digfilt[i]);
11552 }
11553 
11554 static void
11555 bwn_phy_lp_tblinit(struct bwn_mac *mac)
11556 {
11557 	uint32_t freq = ieee80211_ieee2mhz(bwn_phy_lp_get_default_chan(mac), 0);
11558 
11559 	if (mac->mac_phy.rev < 2) {
11560 		bwn_phy_lp_tblinit_r01(mac);
11561 		bwn_phy_lp_tblinit_txgain(mac);
11562 		bwn_phy_lp_set_gaintbl(mac, freq);
11563 		return;
11564 	}
11565 
11566 	bwn_phy_lp_tblinit_r2(mac);
11567 	bwn_phy_lp_tblinit_txgain(mac);
11568 }
11569 
11570 struct bwn_wpair {
11571 	uint16_t		reg;
11572 	uint16_t		value;
11573 };
11574 
11575 struct bwn_smpair {
11576 	uint16_t		offset;
11577 	uint16_t		mask;
11578 	uint16_t		set;
11579 };
11580 
11581 static void
11582 bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
11583 {
11584 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11585 	struct bwn_softc *sc = mac->mac_sc;
11586 	struct ieee80211com *ic = &sc->sc_ic;
11587 	static const struct bwn_wpair v1[] = {
11588 		{ BWN_PHY_AFE_DAC_CTL, 0x50 },
11589 		{ BWN_PHY_AFE_CTL, 0x8800 },
11590 		{ BWN_PHY_AFE_CTL_OVR, 0 },
11591 		{ BWN_PHY_AFE_CTL_OVRVAL, 0 },
11592 		{ BWN_PHY_RF_OVERRIDE_0, 0 },
11593 		{ BWN_PHY_RF_OVERRIDE_2, 0 },
11594 		{ BWN_PHY_OFDM(0xf9), 0 },
11595 		{ BWN_PHY_TR_LOOKUP_1, 0 }
11596 	};
11597 	static const struct bwn_smpair v2[] = {
11598 		{ BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0xb4 },
11599 		{ BWN_PHY_DCOFFSETTRANSIENT, 0xf8ff, 0x200 },
11600 		{ BWN_PHY_DCOFFSETTRANSIENT, 0xff00, 0x7f },
11601 		{ BWN_PHY_GAINDIRECTMISMATCH, 0xff0f, 0x40 },
11602 		{ BWN_PHY_PREAMBLECONFIRMTO, 0xff00, 0x2 }
11603 	};
11604 	static const struct bwn_smpair v3[] = {
11605 		{ BWN_PHY_OFDM(0xfe), 0xffe0, 0x1f },
11606 		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11607 		{ BWN_PHY_OFDM(0x100), 0xff00, 0x19 },
11608 		{ BWN_PHY_OFDM(0xff), 0x03ff, 0x3c00 },
11609 		{ BWN_PHY_OFDM(0xfe), 0xfc1f, 0x3e0 },
11610 		{ BWN_PHY_OFDM(0xff), 0xffe0, 0xc },
11611 		{ BWN_PHY_OFDM(0x100), 0x00ff, 0x1900 },
11612 		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800 },
11613 		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x12 },
11614 		{ BWN_PHY_GAINMISMATCH, 0x0fff, 0x9000 },
11615 
11616 	};
11617 	int i;
11618 
11619 	for (i = 0; i < N(v1); i++)
11620 		BWN_PHY_WRITE(mac, v1[i].reg, v1[i].value);
11621 	BWN_PHY_SET(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x10);
11622 	for (i = 0; i < N(v2); i++)
11623 		BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask, v2[i].set);
11624 
11625 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x4000);
11626 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x2000);
11627 	BWN_PHY_SET(mac, BWN_PHY_OFDM(0x10a), 0x1);
11628 	if (siba_get_pci_revid(sc->sc_dev) >= 0x18) {
11629 		bwn_tab_write(mac, BWN_TAB_4(17, 65), 0xec);
11630 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x14);
11631 	} else {
11632 		BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0x10a), 0xff01, 0x10);
11633 	}
11634 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0xff00, 0xf4);
11635 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xdf), 0x00ff, 0xf100);
11636 	BWN_PHY_WRITE(mac, BWN_PHY_CLIPTHRESH, 0x48);
11637 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0xff00, 0x46);
11638 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe4), 0xff00, 0x10);
11639 	BWN_PHY_SETMASK(mac, BWN_PHY_PWR_THRESH1, 0xfff0, 0x9);
11640 	BWN_PHY_MASK(mac, BWN_PHY_GAINDIRECTMISMATCH, ~0xf);
11641 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5500);
11642 	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0xa0);
11643 	BWN_PHY_SETMASK(mac, BWN_PHY_GAINDIRECTMISMATCH, 0xe0ff, 0x300);
11644 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2a00);
11645 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11646 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11647 		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11648 		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xa);
11649 	} else {
11650 		BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x1e00);
11651 		BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0xd);
11652 	}
11653 	for (i = 0; i < N(v3); i++)
11654 		BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask, v3[i].set);
11655 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11656 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11657 		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x14), 0);
11658 		bwn_tab_write(mac, BWN_TAB_2(0x08, 0x12), 0x40);
11659 	}
11660 
11661 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11662 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x40);
11663 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0xb00);
11664 		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x6);
11665 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0x9d00);
11666 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0xff00, 0xa1);
11667 		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11668 	} else
11669 		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, ~0x40);
11670 
11671 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0xff00, 0xb3);
11672 	BWN_PHY_SETMASK(mac, BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00);
11673 	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB, 0xff00, plp->plp_rxpwroffset);
11674 	BWN_PHY_SET(mac, BWN_PHY_RESET_CTL, 0x44);
11675 	BWN_PHY_WRITE(mac, BWN_PHY_RESET_CTL, 0x80);
11676 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, 0xa954);
11677 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_1,
11678 	    0x2000 | ((uint16_t)plp->plp_rssigs << 10) |
11679 	    ((uint16_t)plp->plp_rssivc << 4) | plp->plp_rssivf);
11680 
11681 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
11682 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
11683 		BWN_PHY_SET(mac, BWN_PHY_AFE_ADC_CTL_0, 0x1c);
11684 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_CTL, 0x00ff, 0x8800);
11685 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_1, 0xfc3c, 0x0400);
11686 	}
11687 
11688 	bwn_phy_lp_digflt_save(mac);
11689 }
11690 
11691 static void
11692 bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
11693 {
11694 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11695 	struct bwn_softc *sc = mac->mac_sc;
11696 	struct ieee80211com *ic = &sc->sc_ic;
11697 	static const struct bwn_smpair v1[] = {
11698 		{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
11699 		{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
11700 		{ BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x3c00 },
11701 		{ BWN_PHY_GAINDIRECTMISMATCH, 0xfff0, 0x0005 },
11702 		{ BWN_PHY_GAIN_MISMATCH_LIMIT, 0xffc0, 0x001a },
11703 		{ BWN_PHY_CRS_ED_THRESH, 0xff00, 0x00b3 },
11704 		{ BWN_PHY_CRS_ED_THRESH, 0x00ff, 0xad00 }
11705 	};
11706 	static const struct bwn_smpair v2[] = {
11707 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11708 		{ BWN_PHY_TR_LOOKUP_1, 0x3f00, 0x0900 },
11709 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11710 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11711 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x000a },
11712 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0400 },
11713 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x000a },
11714 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0b00 },
11715 		{ BWN_PHY_TR_LOOKUP_5, 0xffc0, 0x000a },
11716 		{ BWN_PHY_TR_LOOKUP_5, 0xc0ff, 0x0900 },
11717 		{ BWN_PHY_TR_LOOKUP_6, 0xffc0, 0x000a },
11718 		{ BWN_PHY_TR_LOOKUP_6, 0xc0ff, 0x0b00 },
11719 		{ BWN_PHY_TR_LOOKUP_7, 0xffc0, 0x000a },
11720 		{ BWN_PHY_TR_LOOKUP_7, 0xc0ff, 0x0900 },
11721 		{ BWN_PHY_TR_LOOKUP_8, 0xffc0, 0x000a },
11722 		{ BWN_PHY_TR_LOOKUP_8, 0xc0ff, 0x0b00 }
11723 	};
11724 	static const struct bwn_smpair v3[] = {
11725 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0001 },
11726 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0400 },
11727 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0001 },
11728 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0500 },
11729 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11730 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0800 },
11731 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11732 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0a00 }
11733 	};
11734 	static const struct bwn_smpair v4[] = {
11735 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x0004 },
11736 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0800 },
11737 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x0004 },
11738 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0c00 },
11739 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0002 },
11740 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0100 },
11741 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0002 },
11742 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0300 }
11743 	};
11744 	static const struct bwn_smpair v5[] = {
11745 		{ BWN_PHY_TR_LOOKUP_1, 0xffc0, 0x000a },
11746 		{ BWN_PHY_TR_LOOKUP_1, 0xc0ff, 0x0900 },
11747 		{ BWN_PHY_TR_LOOKUP_2, 0xffc0, 0x000a },
11748 		{ BWN_PHY_TR_LOOKUP_2, 0xc0ff, 0x0b00 },
11749 		{ BWN_PHY_TR_LOOKUP_3, 0xffc0, 0x0006 },
11750 		{ BWN_PHY_TR_LOOKUP_3, 0xc0ff, 0x0500 },
11751 		{ BWN_PHY_TR_LOOKUP_4, 0xffc0, 0x0006 },
11752 		{ BWN_PHY_TR_LOOKUP_4, 0xc0ff, 0x0700 }
11753 	};
11754 	int i;
11755 	uint16_t tmp, tmp2;
11756 
11757 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf7ff);
11758 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL, 0);
11759 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, 0);
11760 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, 0);
11761 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0);
11762 	BWN_PHY_SET(mac, BWN_PHY_AFE_DAC_CTL, 0x0004);
11763 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDMSYNCTHRESH0, 0xff00, 0x0078);
11764 	BWN_PHY_SETMASK(mac, BWN_PHY_CLIPCTRTHRESH, 0x83ff, 0x5800);
11765 	BWN_PHY_WRITE(mac, BWN_PHY_ADC_COMPENSATION_CTL, 0x0016);
11766 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_ADC_CTL_0, 0xfff8, 0x0004);
11767 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0x00ff, 0x5400);
11768 	BWN_PHY_SETMASK(mac, BWN_PHY_HIGAINDB, 0x00ff, 0x2400);
11769 	BWN_PHY_SETMASK(mac, BWN_PHY_LOWGAINDB, 0x00ff, 0x2100);
11770 	BWN_PHY_SETMASK(mac, BWN_PHY_VERYLOWGAINDB, 0xff00, 0x0006);
11771 	BWN_PHY_MASK(mac, BWN_PHY_RX_RADIO_CTL, 0xfffe);
11772 	for (i = 0; i < N(v1); i++)
11773 		BWN_PHY_SETMASK(mac, v1[i].offset, v1[i].mask, v1[i].set);
11774 	BWN_PHY_SETMASK(mac, BWN_PHY_INPUT_PWRDB,
11775 	    0xff00, plp->plp_rxpwroffset);
11776 	if ((siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM) &&
11777 	    ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ||
11778 	   (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF))) {
11779 		siba_cc_pmu_set_ldovolt(sc->sc_dev, SIBA_LDO_PAREF, 0x28);
11780 		siba_cc_pmu_set_ldoparef(sc->sc_dev, 1);
11781 		if (mac->mac_phy.rev == 0)
11782 			BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT,
11783 			    0xffcf, 0x0010);
11784 		bwn_tab_write(mac, BWN_TAB_2(11, 7), 60);
11785 	} else {
11786 		siba_cc_pmu_set_ldoparef(sc->sc_dev, 0);
11787 		BWN_PHY_SETMASK(mac, BWN_PHY_LP_RF_SIGNAL_LUT, 0xffcf, 0x0020);
11788 		bwn_tab_write(mac, BWN_TAB_2(11, 7), 100);
11789 	}
11790 	tmp = plp->plp_rssivf | plp->plp_rssivc << 4 | 0xa000;
11791 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_RSSI_CTL_0, tmp);
11792 	if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_RSSIINV)
11793 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x0aaa);
11794 	else
11795 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_RSSI_CTL_1, 0xf000, 0x02aa);
11796 	bwn_tab_write(mac, BWN_TAB_2(11, 1), 24);
11797 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_RADIO_CTL,
11798 	    0xfff9, (plp->plp_bxarch << 1));
11799 	if (mac->mac_phy.rev == 1 &&
11800 	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT)) {
11801 		for (i = 0; i < N(v2); i++)
11802 			BWN_PHY_SETMASK(mac, v2[i].offset, v2[i].mask,
11803 			    v2[i].set);
11804 	} else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ||
11805 	    (siba_get_pci_subdevice(sc->sc_dev) == 0x048a) ||
11806 	    ((mac->mac_phy.rev == 0) &&
11807 	     (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM))) {
11808 		for (i = 0; i < N(v3); i++)
11809 			BWN_PHY_SETMASK(mac, v3[i].offset, v3[i].mask,
11810 			    v3[i].set);
11811 	} else if (mac->mac_phy.rev == 1 ||
11812 		  (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_FEM)) {
11813 		for (i = 0; i < N(v4); i++)
11814 			BWN_PHY_SETMASK(mac, v4[i].offset, v4[i].mask,
11815 			    v4[i].set);
11816 	} else {
11817 		for (i = 0; i < N(v5); i++)
11818 			BWN_PHY_SETMASK(mac, v5[i].offset, v5[i].mask,
11819 			    v5[i].set);
11820 	}
11821 	if (mac->mac_phy.rev == 1 &&
11822 	    (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_LDO_PAREF)) {
11823 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_5, BWN_PHY_TR_LOOKUP_1);
11824 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_6, BWN_PHY_TR_LOOKUP_2);
11825 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_7, BWN_PHY_TR_LOOKUP_3);
11826 		BWN_PHY_COPY(mac, BWN_PHY_TR_LOOKUP_8, BWN_PHY_TR_LOOKUP_4);
11827 	}
11828 	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_FEM_BT) &&
11829 	    (siba_get_chipid(sc->sc_dev) == 0x5354) &&
11830 	    (siba_get_chippkg(sc->sc_dev) == SIBA_CHIPPACK_BCM4712S)) {
11831 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0006);
11832 		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_SELECT, 0x0005);
11833 		BWN_PHY_WRITE(mac, BWN_PHY_GPIO_OUTEN, 0xffff);
11834 		bwn_hf_write(mac, bwn_hf_read(mac) | BWN_HF_PR45960W);
11835 	}
11836 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
11837 		BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x8000);
11838 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x0040);
11839 		BWN_PHY_SETMASK(mac, BWN_PHY_MINPWR_LEVEL, 0x00ff, 0xa400);
11840 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xf0ff, 0x0b00);
11841 		BWN_PHY_SETMASK(mac, BWN_PHY_SYNCPEAKCNT, 0xfff8, 0x0007);
11842 		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xfff8, 0x0003);
11843 		BWN_PHY_SETMASK(mac, BWN_PHY_DSSS_CONFIRM_CNT, 0xffc7, 0x0020);
11844 		BWN_PHY_MASK(mac, BWN_PHY_IDLEAFTERPKTRXTO, 0x00ff);
11845 	} else {
11846 		BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0x7fff);
11847 		BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xffbf);
11848 	}
11849 	if (mac->mac_phy.rev == 1) {
11850 		tmp = BWN_PHY_READ(mac, BWN_PHY_CLIPCTRTHRESH);
11851 		tmp2 = (tmp & 0x03e0) >> 5;
11852 		tmp2 |= tmp2 << 5;
11853 		BWN_PHY_WRITE(mac, BWN_PHY_4C3, tmp2);
11854 		tmp = BWN_PHY_READ(mac, BWN_PHY_GAINDIRECTMISMATCH);
11855 		tmp2 = (tmp & 0x1f00) >> 8;
11856 		tmp2 |= tmp2 << 5;
11857 		BWN_PHY_WRITE(mac, BWN_PHY_4C4, tmp2);
11858 		tmp = BWN_PHY_READ(mac, BWN_PHY_VERYLOWGAINDB);
11859 		tmp2 = tmp & 0x00ff;
11860 		tmp2 |= tmp << 8;
11861 		BWN_PHY_WRITE(mac, BWN_PHY_4C5, tmp2);
11862 	}
11863 }
11864 
11865 struct bwn_b2062_freq {
11866 	uint16_t		freq;
11867 	uint8_t			value[6];
11868 };
11869 
11870 static void
11871 bwn_phy_lp_b2062_init(struct bwn_mac *mac)
11872 {
11873 #define	CALC_CTL7(freq, div)						\
11874 	(((800000000 * (div) + (freq)) / (2 * (freq)) - 8) & 0xff)
11875 #define	CALC_CTL18(freq, div)						\
11876 	((((100 * (freq) + 16000000 * (div)) / (32000000 * (div))) - 1) & 0xff)
11877 #define	CALC_CTL19(freq, div)						\
11878 	((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
11879 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
11880 	struct bwn_softc *sc = mac->mac_sc;
11881 	struct ieee80211com *ic = &sc->sc_ic;
11882 	static const struct bwn_b2062_freq freqdata_tab[] = {
11883 		{ 12000, { 6, 6, 6, 6, 10, 6 } },
11884 		{ 13000, { 4, 4, 4, 4, 11, 7 } },
11885 		{ 14400, { 3, 3, 3, 3, 12, 7 } },
11886 		{ 16200, { 3, 3, 3, 3, 13, 8 } },
11887 		{ 18000, { 2, 2, 2, 2, 14, 8 } },
11888 		{ 19200, { 1, 1, 1, 1, 14, 9 } }
11889 	};
11890 	static const struct bwn_wpair v1[] = {
11891 		{ BWN_B2062_N_TXCTL3, 0 },
11892 		{ BWN_B2062_N_TXCTL4, 0 },
11893 		{ BWN_B2062_N_TXCTL5, 0 },
11894 		{ BWN_B2062_N_TXCTL6, 0 },
11895 		{ BWN_B2062_N_PDNCTL0, 0x40 },
11896 		{ BWN_B2062_N_PDNCTL0, 0 },
11897 		{ BWN_B2062_N_CALIB_TS, 0x10 },
11898 		{ BWN_B2062_N_CALIB_TS, 0 }
11899 	};
11900 	const struct bwn_b2062_freq *f = NULL;
11901 	uint32_t xtalfreq, ref;
11902 	unsigned int i;
11903 
11904 	bwn_phy_lp_b2062_tblinit(mac);
11905 
11906 	for (i = 0; i < N(v1); i++)
11907 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
11908 	if (mac->mac_phy.rev > 0)
11909 		BWN_RF_WRITE(mac, BWN_B2062_S_BG_CTL1,
11910 		    (BWN_RF_READ(mac, BWN_B2062_N_COM2) >> 1) | 0x80);
11911 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
11912 		BWN_RF_SET(mac, BWN_B2062_N_TSSI_CTL0, 0x1);
11913 	else
11914 		BWN_RF_MASK(mac, BWN_B2062_N_TSSI_CTL0, ~0x1);
11915 
11916 	KASSERT(siba_get_cc_caps(sc->sc_dev) & SIBA_CC_CAPS_PMU,
11917 	    ("%s:%d: fail", __func__, __LINE__));
11918 	xtalfreq = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
11919 	KASSERT(xtalfreq != 0, ("%s:%d: fail", __func__, __LINE__));
11920 
11921 	if (xtalfreq <= 30000000) {
11922 		plp->plp_div = 1;
11923 		BWN_RF_MASK(mac, BWN_B2062_S_RFPLLCTL1, 0xfffb);
11924 	} else {
11925 		plp->plp_div = 2;
11926 		BWN_RF_SET(mac, BWN_B2062_S_RFPLLCTL1, 0x4);
11927 	}
11928 
11929 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL7,
11930 	    CALC_CTL7(xtalfreq, plp->plp_div));
11931 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL18,
11932 	    CALC_CTL18(xtalfreq, plp->plp_div));
11933 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL19,
11934 	    CALC_CTL19(xtalfreq, plp->plp_div));
11935 
11936 	ref = (1000 * plp->plp_div + 2 * xtalfreq) / (2000 * plp->plp_div);
11937 	ref &= 0xffff;
11938 	for (i = 0; i < N(freqdata_tab); i++) {
11939 		if (ref < freqdata_tab[i].freq) {
11940 			f = &freqdata_tab[i];
11941 			break;
11942 		}
11943 	}
11944 	if (f == NULL)
11945 		f = &freqdata_tab[N(freqdata_tab) - 1];
11946 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL8,
11947 	    ((uint16_t)(f->value[1]) << 4) | f->value[0]);
11948 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL9,
11949 	    ((uint16_t)(f->value[3]) << 4) | f->value[2]);
11950 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL10, f->value[4]);
11951 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL11, f->value[5]);
11952 #undef CALC_CTL7
11953 #undef CALC_CTL18
11954 #undef CALC_CTL19
11955 }
11956 
11957 static void
11958 bwn_phy_lp_b2063_init(struct bwn_mac *mac)
11959 {
11960 
11961 	bwn_phy_lp_b2063_tblinit(mac);
11962 	BWN_RF_WRITE(mac, BWN_B2063_LOGEN_SP5, 0);
11963 	BWN_RF_SET(mac, BWN_B2063_COM8, 0x38);
11964 	BWN_RF_WRITE(mac, BWN_B2063_REG_SP1, 0x56);
11965 	BWN_RF_MASK(mac, BWN_B2063_RX_BB_CTL2, ~0x2);
11966 	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0);
11967 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP6, 0x20);
11968 	BWN_RF_WRITE(mac, BWN_B2063_TX_RF_SP9, 0x40);
11969 	if (mac->mac_phy.rev == 2) {
11970 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0xa0);
11971 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP4, 0xa0);
11972 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x18);
11973 	} else {
11974 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP3, 0x20);
11975 		BWN_RF_WRITE(mac, BWN_B2063_PA_SP2, 0x20);
11976 	}
11977 }
11978 
11979 static void
11980 bwn_phy_lp_rxcal_r2(struct bwn_mac *mac)
11981 {
11982 	struct bwn_softc *sc = mac->mac_sc;
11983 	static const struct bwn_wpair v1[] = {
11984 		{ BWN_B2063_RX_BB_SP8, 0x0 },
11985 		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
11986 		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
11987 		{ BWN_B2063_RC_CALIB_CTL2, 0x15 },
11988 		{ BWN_B2063_RC_CALIB_CTL3, 0x70 },
11989 		{ BWN_B2063_RC_CALIB_CTL4, 0x52 },
11990 		{ BWN_B2063_RC_CALIB_CTL5, 0x1 },
11991 		{ BWN_B2063_RC_CALIB_CTL1, 0x7d }
11992 	};
11993 	static const struct bwn_wpair v2[] = {
11994 		{ BWN_B2063_TX_BB_SP3, 0x0 },
11995 		{ BWN_B2063_RC_CALIB_CTL1, 0x7e },
11996 		{ BWN_B2063_RC_CALIB_CTL1, 0x7c },
11997 		{ BWN_B2063_RC_CALIB_CTL2, 0x55 },
11998 		{ BWN_B2063_RC_CALIB_CTL3, 0x76 }
11999 	};
12000 	uint32_t freqxtal = siba_get_cc_pmufreq(sc->sc_dev) * 1000;
12001 	int i;
12002 	uint8_t tmp;
12003 
12004 	tmp = BWN_RF_READ(mac, BWN_B2063_RX_BB_SP8) & 0xff;
12005 
12006 	for (i = 0; i < 2; i++)
12007 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12008 	BWN_RF_MASK(mac, BWN_B2063_PLL_SP1, 0xf7);
12009 	for (i = 2; i < N(v1); i++)
12010 		BWN_RF_WRITE(mac, v1[i].reg, v1[i].value);
12011 	for (i = 0; i < 10000; i++) {
12012 		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12013 			break;
12014 		DELAY(1000);
12015 	}
12016 
12017 	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12018 		BWN_RF_WRITE(mac, BWN_B2063_RX_BB_SP8, tmp);
12019 
12020 	tmp = BWN_RF_READ(mac, BWN_B2063_TX_BB_SP3) & 0xff;
12021 
12022 	for (i = 0; i < N(v2); i++)
12023 		BWN_RF_WRITE(mac, v2[i].reg, v2[i].value);
12024 	if (freqxtal == 24000000) {
12025 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0xfc);
12026 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x0);
12027 	} else {
12028 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL4, 0x13);
12029 		BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL5, 0x1);
12030 	}
12031 	BWN_RF_WRITE(mac, BWN_B2063_PA_SP7, 0x7d);
12032 	for (i = 0; i < 10000; i++) {
12033 		if (BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2)
12034 			break;
12035 		DELAY(1000);
12036 	}
12037 	if (!(BWN_RF_READ(mac, BWN_B2063_RC_CALIB_CTL6) & 0x2))
12038 		BWN_RF_WRITE(mac, BWN_B2063_TX_BB_SP3, tmp);
12039 	BWN_RF_WRITE(mac, BWN_B2063_RC_CALIB_CTL1, 0x7e);
12040 }
12041 
12042 static void
12043 bwn_phy_lp_rccal_r12(struct bwn_mac *mac)
12044 {
12045 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12046 	struct bwn_softc *sc = mac->mac_sc;
12047 	struct bwn_phy_lp_iq_est ie;
12048 	struct bwn_txgain tx_gains;
12049 	static const uint32_t pwrtbl[21] = {
12050 		0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
12051 		0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
12052 		0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
12053 		0x0004c, 0x0002c, 0x0001a,
12054 	};
12055 	uint32_t npwr, ipwr, sqpwr, tmp;
12056 	int loopback, i, j, sum, error;
12057 	uint16_t save[7];
12058 	uint8_t txo, bbmult, txpctlmode;
12059 
12060 	error = bwn_phy_lp_switch_channel(mac, 7);
12061 	if (error)
12062 		device_printf(sc->sc_dev,
12063 		    "failed to change channel to 7 (%d)\n", error);
12064 	txo = (BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR) & 0x40) ? 1 : 0;
12065 	bbmult = bwn_phy_lp_get_bbmult(mac);
12066 	if (txo)
12067 		tx_gains = bwn_phy_lp_get_txgain(mac);
12068 
12069 	save[0] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_0);
12070 	save[1] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_VAL_0);
12071 	save[2] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVR);
12072 	save[3] = BWN_PHY_READ(mac, BWN_PHY_AFE_CTL_OVRVAL);
12073 	save[4] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2);
12074 	save[5] = BWN_PHY_READ(mac, BWN_PHY_RF_OVERRIDE_2_VAL);
12075 	save[6] = BWN_PHY_READ(mac, BWN_PHY_LP_PHY_CTL);
12076 
12077 	bwn_phy_lp_get_txpctlmode(mac);
12078 	txpctlmode = plp->plp_txpctlmode;
12079 	bwn_phy_lp_set_txpctlmode(mac, BWN_PHYLP_TXPCTL_OFF);
12080 
12081 	/* disable CRS */
12082 	bwn_phy_lp_set_deaf(mac, 1);
12083 	bwn_phy_lp_set_trsw_over(mac, 0, 1);
12084 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffb);
12085 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x4);
12086 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfff7);
12087 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
12088 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x10);
12089 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12090 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffdf);
12091 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x20);
12092 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xffbf);
12093 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12094 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x7);
12095 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x38);
12096 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f);
12097 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0x100);
12098 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfdff);
12099 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL0, 0);
12100 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL1, 1);
12101 	BWN_PHY_WRITE(mac, BWN_PHY_PS_CTL_OVERRIDE_VAL2, 0x20);
12102 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfbff);
12103 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xf7ff);
12104 	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
12105 	BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45af);
12106 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, 0x3ff);
12107 
12108 	loopback = bwn_phy_lp_loopback(mac);
12109 	if (loopback == -1)
12110 		goto done;
12111 	bwn_phy_lp_set_rxgain_idx(mac, loopback);
12112 	BWN_PHY_SETMASK(mac, BWN_PHY_LP_PHY_CTL, 0xffbf, 0x40);
12113 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xfff8, 0x1);
12114 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xffc7, 0x8);
12115 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL, 0xff3f, 0xc0);
12116 
12117 	tmp = 0;
12118 	memset(&ie, 0, sizeof(ie));
12119 	for (i = 128; i <= 159; i++) {
12120 		BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2, i);
12121 		sum = 0;
12122 		for (j = 5; j <= 25; j++) {
12123 			bwn_phy_lp_ddfs_turnon(mac, 1, 1, j, j, 0);
12124 			if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
12125 				goto done;
12126 			sqpwr = ie.ie_ipwr + ie.ie_qpwr;
12127 			ipwr = ((pwrtbl[j - 5] >> 3) + 1) >> 1;
12128 			npwr = bwn_phy_lp_roundup(sqpwr, (j == 5) ? sqpwr : 0,
12129 			    12);
12130 			sum += ((ipwr - npwr) * (ipwr - npwr));
12131 			if ((i == 128) || (sum < tmp)) {
12132 				plp->plp_rccap = i;
12133 				tmp = sum;
12134 			}
12135 		}
12136 	}
12137 	bwn_phy_lp_ddfs_turnoff(mac);
12138 done:
12139 	/* restore CRS */
12140 	bwn_phy_lp_clear_deaf(mac, 1);
12141 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_0, 0xff80);
12142 	BWN_PHY_MASK(mac, BWN_PHY_RF_OVERRIDE_2, 0xfc00);
12143 
12144 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_VAL_0, save[1]);
12145 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_0, save[0]);
12146 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVRVAL, save[3]);
12147 	BWN_PHY_WRITE(mac, BWN_PHY_AFE_CTL_OVR, save[2]);
12148 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2_VAL, save[5]);
12149 	BWN_PHY_WRITE(mac, BWN_PHY_RF_OVERRIDE_2, save[4]);
12150 	BWN_PHY_WRITE(mac, BWN_PHY_LP_PHY_CTL, save[6]);
12151 
12152 	bwn_phy_lp_set_bbmult(mac, bbmult);
12153 	if (txo)
12154 		bwn_phy_lp_set_txgain(mac, &tx_gains);
12155 	bwn_phy_lp_set_txpctlmode(mac, txpctlmode);
12156 	if (plp->plp_rccap)
12157 		bwn_phy_lp_set_rccap(mac);
12158 }
12159 
12160 static void
12161 bwn_phy_lp_set_rccap(struct bwn_mac *mac)
12162 {
12163 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12164 	uint8_t rc_cap = (plp->plp_rccap & 0x1f) >> 1;
12165 
12166 	if (mac->mac_phy.rev == 1)
12167 		rc_cap = MIN(rc_cap + 5, 15);
12168 
12169 	BWN_RF_WRITE(mac, BWN_B2062_N_RXBB_CALIB2,
12170 	    MAX(plp->plp_rccap - 4, 0x80));
12171 	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, rc_cap | 0x80);
12172 	BWN_RF_WRITE(mac, BWN_B2062_S_RXG_CNT16,
12173 	    ((plp->plp_rccap & 0x1f) >> 2) | 0x80);
12174 }
12175 
12176 static uint32_t
12177 bwn_phy_lp_roundup(uint32_t value, uint32_t div, uint8_t pre)
12178 {
12179 	uint32_t i, q, r;
12180 
12181 	if (div == 0)
12182 		return (0);
12183 
12184 	for (i = 0, q = value / div, r = value % div; i < pre; i++) {
12185 		q <<= 1;
12186 		if (r << 1 >= div) {
12187 			q++;
12188 			r = (r << 1) - div;
12189 		}
12190 	}
12191 	if (r << 1 >= div)
12192 		q++;
12193 	return (q);
12194 }
12195 
12196 static void
12197 bwn_phy_lp_b2062_reset_pllbias(struct bwn_mac *mac)
12198 {
12199 	struct bwn_softc *sc = mac->mac_sc;
12200 
12201 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0xff);
12202 	DELAY(20);
12203 	if (siba_get_chipid(sc->sc_dev) == 0x5354) {
12204 		BWN_RF_WRITE(mac, BWN_B2062_N_COM1, 4);
12205 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 4);
12206 	} else {
12207 		BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL2, 0);
12208 	}
12209 	DELAY(5);
12210 }
12211 
12212 static void
12213 bwn_phy_lp_b2062_vco_calib(struct bwn_mac *mac)
12214 {
12215 
12216 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x42);
12217 	BWN_RF_WRITE(mac, BWN_B2062_S_RFPLLCTL21, 0x62);
12218 	DELAY(200);
12219 }
12220 
12221 static void
12222 bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
12223 {
12224 #define	FLAG_A	0x01
12225 #define	FLAG_G	0x02
12226 	struct bwn_softc *sc = mac->mac_sc;
12227 	struct ieee80211com *ic = &sc->sc_ic;
12228 	static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
12229 		{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12230 		{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
12231 		{ BWN_B2062_N_PDNCTL3, 0x0, 0x0, FLAG_A | FLAG_G, },
12232 		{ BWN_B2062_N_PDNCTL4, 0x15, 0x2a, FLAG_A | FLAG_G, },
12233 		{ BWN_B2062_N_LGENC, 0xDB, 0xff, FLAG_A, },
12234 		{ BWN_B2062_N_LGENATUNE0, 0xdd, 0x0, FLAG_A | FLAG_G, },
12235 		{ BWN_B2062_N_LGENATUNE2, 0xdd, 0x0, FLAG_A | FLAG_G, },
12236 		{ BWN_B2062_N_LGENATUNE3, 0x77, 0xB5, FLAG_A | FLAG_G, },
12237 		{ BWN_B2062_N_LGENACTL3, 0x0, 0xff, FLAG_A | FLAG_G, },
12238 		{ BWN_B2062_N_LGENACTL7, 0x33, 0x33, FLAG_A | FLAG_G, },
12239 		{ BWN_B2062_N_RXA_CTL1, 0x0, 0x0, FLAG_G, },
12240 		{ BWN_B2062_N_RXBB_CTL0, 0x82, 0x80, FLAG_A | FLAG_G, },
12241 		{ BWN_B2062_N_RXBB_GAIN1, 0x4, 0x4, FLAG_A | FLAG_G, },
12242 		{ BWN_B2062_N_RXBB_GAIN2, 0x0, 0x0, FLAG_A | FLAG_G, },
12243 		{ BWN_B2062_N_TXCTL4, 0x3, 0x3, FLAG_A | FLAG_G, },
12244 		{ BWN_B2062_N_TXCTL5, 0x2, 0x2, FLAG_A | FLAG_G, },
12245 		{ BWN_B2062_N_TX_TUNE, 0x88, 0x1b, FLAG_A | FLAG_G, },
12246 		{ BWN_B2062_S_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
12247 		{ BWN_B2062_S_PDS_CTL0, 0xff, 0xff, FLAG_A | FLAG_G, },
12248 		{ BWN_B2062_S_LGENG_CTL0, 0xf8, 0xd8, FLAG_A | FLAG_G, },
12249 		{ BWN_B2062_S_LGENG_CTL1, 0x3c, 0x24, FLAG_A | FLAG_G, },
12250 		{ BWN_B2062_S_LGENG_CTL8, 0x88, 0x80, FLAG_A | FLAG_G, },
12251 		{ BWN_B2062_S_LGENG_CTL10, 0x88, 0x80, FLAG_A | FLAG_G, },
12252 		{ BWN_B2062_S_RFPLLCTL0, 0x98, 0x98, FLAG_A | FLAG_G, },
12253 		{ BWN_B2062_S_RFPLLCTL1, 0x10, 0x10, FLAG_A | FLAG_G, },
12254 		{ BWN_B2062_S_RFPLLCTL5, 0x43, 0x43, FLAG_A | FLAG_G, },
12255 		{ BWN_B2062_S_RFPLLCTL6, 0x47, 0x47, FLAG_A | FLAG_G, },
12256 		{ BWN_B2062_S_RFPLLCTL7, 0xc, 0xc, FLAG_A | FLAG_G, },
12257 		{ BWN_B2062_S_RFPLLCTL8, 0x11, 0x11, FLAG_A | FLAG_G, },
12258 		{ BWN_B2062_S_RFPLLCTL9, 0x11, 0x11, FLAG_A | FLAG_G, },
12259 		{ BWN_B2062_S_RFPLLCTL10, 0xe, 0xe, FLAG_A | FLAG_G, },
12260 		{ BWN_B2062_S_RFPLLCTL11, 0x8, 0x8, FLAG_A | FLAG_G, },
12261 		{ BWN_B2062_S_RFPLLCTL12, 0x33, 0x33, FLAG_A | FLAG_G, },
12262 		{ BWN_B2062_S_RFPLLCTL13, 0xa, 0xa, FLAG_A | FLAG_G, },
12263 		{ BWN_B2062_S_RFPLLCTL14, 0x6, 0x6, FLAG_A | FLAG_G, },
12264 		{ BWN_B2062_S_RFPLLCTL18, 0x3e, 0x3e, FLAG_A | FLAG_G, },
12265 		{ BWN_B2062_S_RFPLLCTL19, 0x13, 0x13, FLAG_A | FLAG_G, },
12266 		{ BWN_B2062_S_RFPLLCTL21, 0x62, 0x62, FLAG_A | FLAG_G, },
12267 		{ BWN_B2062_S_RFPLLCTL22, 0x7, 0x7, FLAG_A | FLAG_G, },
12268 		{ BWN_B2062_S_RFPLLCTL23, 0x16, 0x16, FLAG_A | FLAG_G, },
12269 		{ BWN_B2062_S_RFPLLCTL24, 0x5c, 0x5c, FLAG_A | FLAG_G, },
12270 		{ BWN_B2062_S_RFPLLCTL25, 0x95, 0x95, FLAG_A | FLAG_G, },
12271 		{ BWN_B2062_S_RFPLLCTL30, 0xa0, 0xa0, FLAG_A | FLAG_G, },
12272 		{ BWN_B2062_S_RFPLLCTL31, 0x4, 0x4, FLAG_A | FLAG_G, },
12273 		{ BWN_B2062_S_RFPLLCTL33, 0xcc, 0xcc, FLAG_A | FLAG_G, },
12274 		{ BWN_B2062_S_RFPLLCTL34, 0x7, 0x7, FLAG_A | FLAG_G, },
12275 		{ BWN_B2062_S_RXG_CNT8, 0xf, 0xf, FLAG_A, },
12276 	};
12277 	const struct bwn_b206x_rfinit_entry *br;
12278 	unsigned int i;
12279 
12280 	for (i = 0; i < N(bwn_b2062_init_tab); i++) {
12281 		br = &bwn_b2062_init_tab[i];
12282 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12283 			if (br->br_flags & FLAG_G)
12284 				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12285 		} else {
12286 			if (br->br_flags & FLAG_A)
12287 				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12288 		}
12289 	}
12290 #undef FLAG_A
12291 #undef FLAG_B
12292 }
12293 
12294 static void
12295 bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
12296 {
12297 #define	FLAG_A	0x01
12298 #define	FLAG_G	0x02
12299 	struct bwn_softc *sc = mac->mac_sc;
12300 	struct ieee80211com *ic = &sc->sc_ic;
12301 	static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
12302 		{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
12303 		{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
12304 		{ BWN_B2063_COM16, 0x0, 0x0, FLAG_G, },
12305 		{ BWN_B2063_COM17, 0x0, 0x0, FLAG_G, },
12306 		{ BWN_B2063_COM18, 0x0, 0x0, FLAG_G, },
12307 		{ BWN_B2063_COM19, 0x0, 0x0, FLAG_G, },
12308 		{ BWN_B2063_COM20, 0x0, 0x0, FLAG_G, },
12309 		{ BWN_B2063_COM21, 0x0, 0x0, FLAG_G, },
12310 		{ BWN_B2063_COM22, 0x0, 0x0, FLAG_G, },
12311 		{ BWN_B2063_COM23, 0x0, 0x0, FLAG_G, },
12312 		{ BWN_B2063_COM24, 0x0, 0x0, FLAG_G, },
12313 		{ BWN_B2063_LOGEN_SP1, 0xe8, 0xd4, FLAG_A | FLAG_G, },
12314 		{ BWN_B2063_LOGEN_SP2, 0xa7, 0x53, FLAG_A | FLAG_G, },
12315 		{ BWN_B2063_LOGEN_SP4, 0xf0, 0xf, FLAG_A | FLAG_G, },
12316 		{ BWN_B2063_G_RX_SP1, 0x1f, 0x5e, FLAG_G, },
12317 		{ BWN_B2063_G_RX_SP2, 0x7f, 0x7e, FLAG_G, },
12318 		{ BWN_B2063_G_RX_SP3, 0x30, 0xf0, FLAG_G, },
12319 		{ BWN_B2063_G_RX_SP7, 0x7f, 0x7f, FLAG_A | FLAG_G, },
12320 		{ BWN_B2063_G_RX_SP10, 0xc, 0xc, FLAG_A | FLAG_G, },
12321 		{ BWN_B2063_A_RX_SP1, 0x3c, 0x3f, FLAG_A, },
12322 		{ BWN_B2063_A_RX_SP2, 0xfc, 0xfe, FLAG_A, },
12323 		{ BWN_B2063_A_RX_SP7, 0x8, 0x8, FLAG_A | FLAG_G, },
12324 		{ BWN_B2063_RX_BB_SP4, 0x60, 0x60, FLAG_A | FLAG_G, },
12325 		{ BWN_B2063_RX_BB_SP8, 0x30, 0x30, FLAG_A | FLAG_G, },
12326 		{ BWN_B2063_TX_RF_SP3, 0xc, 0xb, FLAG_A | FLAG_G, },
12327 		{ BWN_B2063_TX_RF_SP4, 0x10, 0xf, FLAG_A | FLAG_G, },
12328 		{ BWN_B2063_PA_SP1, 0x3d, 0xfd, FLAG_A | FLAG_G, },
12329 		{ BWN_B2063_TX_BB_SP1, 0x2, 0x2, FLAG_A | FLAG_G, },
12330 		{ BWN_B2063_BANDGAP_CTL1, 0x56, 0x56, FLAG_A | FLAG_G, },
12331 		{ BWN_B2063_JTAG_VCO2, 0xF7, 0xF7, FLAG_A | FLAG_G, },
12332 		{ BWN_B2063_G_RX_MIX3, 0x71, 0x71, FLAG_A | FLAG_G, },
12333 		{ BWN_B2063_G_RX_MIX4, 0x71, 0x71, FLAG_A | FLAG_G, },
12334 		{ BWN_B2063_A_RX_1ST2, 0xf0, 0x30, FLAG_A, },
12335 		{ BWN_B2063_A_RX_PS6, 0x77, 0x77, FLAG_A | FLAG_G, },
12336 		{ BWN_B2063_A_RX_MIX4, 0x3, 0x3, FLAG_A | FLAG_G, },
12337 		{ BWN_B2063_A_RX_MIX5, 0xf, 0xf, FLAG_A | FLAG_G, },
12338 		{ BWN_B2063_A_RX_MIX6, 0xf, 0xf, FLAG_A | FLAG_G, },
12339 		{ BWN_B2063_RX_TIA_CTL1, 0x77, 0x77, FLAG_A | FLAG_G, },
12340 		{ BWN_B2063_RX_TIA_CTL3, 0x77, 0x77, FLAG_A | FLAG_G, },
12341 		{ BWN_B2063_RX_BB_CTL2, 0x4, 0x4, FLAG_A | FLAG_G, },
12342 		{ BWN_B2063_PA_CTL1, 0x0, 0x4, FLAG_A, },
12343 		{ BWN_B2063_VREG_CTL1, 0x3, 0x3, FLAG_A | FLAG_G, },
12344 	};
12345 	const struct bwn_b206x_rfinit_entry *br;
12346 	unsigned int i;
12347 
12348 	for (i = 0; i < N(bwn_b2063_init_tab); i++) {
12349 		br = &bwn_b2063_init_tab[i];
12350 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12351 			if (br->br_flags & FLAG_G)
12352 				BWN_RF_WRITE(mac, br->br_offset, br->br_valueg);
12353 		} else {
12354 			if (br->br_flags & FLAG_A)
12355 				BWN_RF_WRITE(mac, br->br_offset, br->br_valuea);
12356 		}
12357 	}
12358 #undef FLAG_A
12359 #undef FLAG_B
12360 }
12361 
12362 static void
12363 bwn_tab_read_multi(struct bwn_mac *mac, uint32_t typenoffset,
12364     int count, void *_data)
12365 {
12366 	unsigned int i;
12367 	uint32_t offset, type;
12368 	uint8_t *data = _data;
12369 
12370 	type = BWN_TAB_GETTYPE(typenoffset);
12371 	offset = BWN_TAB_GETOFFSET(typenoffset);
12372 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12373 
12374 	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12375 
12376 	for (i = 0; i < count; i++) {
12377 		switch (type) {
12378 		case BWN_TAB_8BIT:
12379 			*data = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
12380 			data++;
12381 			break;
12382 		case BWN_TAB_16BIT:
12383 			*((uint16_t *)data) = BWN_PHY_READ(mac,
12384 			    BWN_PHY_TABLEDATALO);
12385 			data += 2;
12386 			break;
12387 		case BWN_TAB_32BIT:
12388 			*((uint32_t *)data) = BWN_PHY_READ(mac,
12389 			    BWN_PHY_TABLEDATAHI);
12390 			*((uint32_t *)data) <<= 16;
12391 			*((uint32_t *)data) |= BWN_PHY_READ(mac,
12392 			    BWN_PHY_TABLEDATALO);
12393 			data += 4;
12394 			break;
12395 		default:
12396 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12397 		}
12398 	}
12399 }
12400 
12401 static void
12402 bwn_tab_write_multi(struct bwn_mac *mac, uint32_t typenoffset,
12403     int count, const void *_data)
12404 {
12405 	uint32_t offset, type, value;
12406 	const uint8_t *data = _data;
12407 	unsigned int i;
12408 
12409 	type = BWN_TAB_GETTYPE(typenoffset);
12410 	offset = BWN_TAB_GETOFFSET(typenoffset);
12411 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
12412 
12413 	BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
12414 
12415 	for (i = 0; i < count; i++) {
12416 		switch (type) {
12417 		case BWN_TAB_8BIT:
12418 			value = *data;
12419 			data++;
12420 			KASSERT(!(value & ~0xff),
12421 			    ("%s:%d: fail", __func__, __LINE__));
12422 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12423 			break;
12424 		case BWN_TAB_16BIT:
12425 			value = *((const uint16_t *)data);
12426 			data += 2;
12427 			KASSERT(!(value & ~0xffff),
12428 			    ("%s:%d: fail", __func__, __LINE__));
12429 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12430 			break;
12431 		case BWN_TAB_32BIT:
12432 			value = *((const uint32_t *)data);
12433 			data += 4;
12434 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
12435 			BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
12436 			break;
12437 		default:
12438 			KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
12439 		}
12440 	}
12441 }
12442 
12443 static struct bwn_txgain
12444 bwn_phy_lp_get_txgain(struct bwn_mac *mac)
12445 {
12446 	struct bwn_txgain tg;
12447 	uint16_t tmp;
12448 
12449 	tg.tg_dac = (BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0x380) >> 7;
12450 	if (mac->mac_phy.rev < 2) {
12451 		tmp = BWN_PHY_READ(mac,
12452 		    BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7ff;
12453 		tg.tg_gm = tmp & 0x0007;
12454 		tg.tg_pga = (tmp & 0x0078) >> 3;
12455 		tg.tg_pad = (tmp & 0x780) >> 7;
12456 		return (tg);
12457 	}
12458 
12459 	tmp = BWN_PHY_READ(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL);
12460 	tg.tg_pad = BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0xff;
12461 	tg.tg_gm = tmp & 0xff;
12462 	tg.tg_pga = (tmp >> 8) & 0xff;
12463 	return (tg);
12464 }
12465 
12466 static uint8_t
12467 bwn_phy_lp_get_bbmult(struct bwn_mac *mac)
12468 {
12469 
12470 	return (bwn_tab_read(mac, BWN_TAB_2(0, 87)) & 0xff00) >> 8;
12471 }
12472 
12473 static void
12474 bwn_phy_lp_set_txgain(struct bwn_mac *mac, struct bwn_txgain *tg)
12475 {
12476 	uint16_t pa;
12477 
12478 	if (mac->mac_phy.rev < 2) {
12479 		BWN_PHY_SETMASK(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL, 0xf800,
12480 		    (tg->tg_pad << 7) | (tg->tg_pga << 3) | tg->tg_gm);
12481 		bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12482 		bwn_phy_lp_set_txgain_override(mac);
12483 		return;
12484 	}
12485 
12486 	pa = bwn_phy_lp_get_pa_gain(mac);
12487 	BWN_PHY_WRITE(mac, BWN_PHY_TX_GAIN_CTL_OVERRIDE_VAL,
12488 	    (tg->tg_pga << 8) | tg->tg_gm);
12489 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0x8000,
12490 	    tg->tg_pad | (pa << 6));
12491 	BWN_PHY_WRITE(mac, BWN_PHY_OFDM(0xfc), (tg->tg_pga << 8) | tg->tg_gm);
12492 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x8000,
12493 	    tg->tg_pad | (pa << 8));
12494 	bwn_phy_lp_set_txgain_dac(mac, tg->tg_dac);
12495 	bwn_phy_lp_set_txgain_override(mac);
12496 }
12497 
12498 static void
12499 bwn_phy_lp_set_bbmult(struct bwn_mac *mac, uint8_t bbmult)
12500 {
12501 
12502 	bwn_tab_write(mac, BWN_TAB_2(0, 87), (uint16_t)bbmult << 8);
12503 }
12504 
12505 static void
12506 bwn_phy_lp_set_trsw_over(struct bwn_mac *mac, uint8_t tx, uint8_t rx)
12507 {
12508 	uint16_t trsw = (tx << 1) | rx;
12509 
12510 	BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffc, trsw);
12511 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x3);
12512 }
12513 
12514 static void
12515 bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
12516 {
12517 	struct bwn_softc *sc = mac->mac_sc;
12518 	struct ieee80211com *ic = &sc->sc_ic;
12519 	uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
12520 
12521 	if (mac->mac_phy.rev < 2) {
12522 		trsw = gain & 0x1;
12523 		lna = (gain & 0xfffc) | ((gain & 0xc) >> 2);
12524 		ext_lna = (gain & 2) >> 1;
12525 
12526 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12527 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12528 		    0xfbff, ext_lna << 10);
12529 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12530 		    0xf7ff, ext_lna << 11);
12531 		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
12532 	} else {
12533 		low_gain = gain & 0xffff;
12534 		high_gain = (gain >> 16) & 0xf;
12535 		ext_lna = (gain >> 21) & 0x1;
12536 		trsw = ~(gain >> 20) & 0x1;
12537 
12538 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0xfffe, trsw);
12539 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12540 		    0xfdff, ext_lna << 9);
12541 		BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12542 		    0xfbff, ext_lna << 10);
12543 		BWN_PHY_WRITE(mac, BWN_PHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
12544 		BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff0, high_gain);
12545 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12546 			tmp = (gain >> 2) & 0x3;
12547 			BWN_PHY_SETMASK(mac, BWN_PHY_RF_OVERRIDE_2_VAL,
12548 			    0xe7ff, tmp<<11);
12549 			BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xe6), 0xffe7,
12550 			    tmp << 3);
12551 		}
12552 	}
12553 
12554 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x1);
12555 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x10);
12556 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x40);
12557 	if (mac->mac_phy.rev >= 2) {
12558 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
12559 		if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
12560 			BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x400);
12561 			BWN_PHY_SET(mac, BWN_PHY_OFDM(0xe5), 0x8);
12562 		}
12563 		return;
12564 	}
12565 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x200);
12566 }
12567 
12568 static void
12569 bwn_phy_lp_set_deaf(struct bwn_mac *mac, uint8_t user)
12570 {
12571 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12572 
12573 	if (user)
12574 		plp->plp_crsusr_off = 1;
12575 	else
12576 		plp->plp_crssys_off = 1;
12577 
12578 	BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x80);
12579 }
12580 
12581 static void
12582 bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
12583 {
12584 	struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
12585 	struct bwn_softc *sc = mac->mac_sc;
12586 	struct ieee80211com *ic = &sc->sc_ic;
12587 
12588 	if (user)
12589 		plp->plp_crsusr_off = 0;
12590 	else
12591 		plp->plp_crssys_off = 0;
12592 
12593 	if (plp->plp_crsusr_off || plp->plp_crssys_off)
12594 		return;
12595 
12596 	if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
12597 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x60);
12598 	else
12599 		BWN_PHY_SETMASK(mac, BWN_PHY_CRSGAIN_CTL, 0xff1f, 0x20);
12600 }
12601 
12602 static unsigned int
12603 bwn_sqrt(struct bwn_mac *mac, unsigned int x)
12604 {
12605 	/* Table holding (10 * sqrt(x)) for x between 1 and 256. */
12606 	static uint8_t sqrt_table[256] = {
12607 		10, 14, 17, 20, 22, 24, 26, 28,
12608 		30, 31, 33, 34, 36, 37, 38, 40,
12609 		41, 42, 43, 44, 45, 46, 47, 48,
12610 		50, 50, 51, 52, 53, 54, 55, 56,
12611 		57, 58, 59, 60, 60, 61, 62, 63,
12612 		64, 64, 65, 66, 67, 67, 68, 69,
12613 		70, 70, 71, 72, 72, 73, 74, 74,
12614 		75, 76, 76, 77, 78, 78, 79, 80,
12615 		80, 81, 81, 82, 83, 83, 84, 84,
12616 		85, 86, 86, 87, 87, 88, 88, 89,
12617 		90, 90, 91, 91, 92, 92, 93, 93,
12618 		94, 94, 95, 95, 96, 96, 97, 97,
12619 		98, 98, 99, 100, 100, 100, 101, 101,
12620 		102, 102, 103, 103, 104, 104, 105, 105,
12621 		106, 106, 107, 107, 108, 108, 109, 109,
12622 		110, 110, 110, 111, 111, 112, 112, 113,
12623 		113, 114, 114, 114, 115, 115, 116, 116,
12624 		117, 117, 117, 118, 118, 119, 119, 120,
12625 		120, 120, 121, 121, 122, 122, 122, 123,
12626 		123, 124, 124, 124, 125, 125, 126, 126,
12627 		126, 127, 127, 128, 128, 128, 129, 129,
12628 		130, 130, 130, 131, 131, 131, 132, 132,
12629 		133, 133, 133, 134, 134, 134, 135, 135,
12630 		136, 136, 136, 137, 137, 137, 138, 138,
12631 		138, 139, 139, 140, 140, 140, 141, 141,
12632 		141, 142, 142, 142, 143, 143, 143, 144,
12633 		144, 144, 145, 145, 145, 146, 146, 146,
12634 		147, 147, 147, 148, 148, 148, 149, 149,
12635 		150, 150, 150, 150, 151, 151, 151, 152,
12636 		152, 152, 153, 153, 153, 154, 154, 154,
12637 		155, 155, 155, 156, 156, 156, 157, 157,
12638 		157, 158, 158, 158, 159, 159, 159, 160
12639 	};
12640 
12641 	if (x == 0)
12642 		return (0);
12643 	if (x >= 256) {
12644 		unsigned int tmp;
12645 
12646 		for (tmp = 0; x >= (2 * tmp) + 1; x -= (2 * tmp++) + 1)
12647 			/* do nothing */ ;
12648 		return (tmp);
12649 	}
12650 	return (sqrt_table[x - 1] / 10);
12651 }
12652 
12653 static int
12654 bwn_phy_lp_calc_rx_iq_comp(struct bwn_mac *mac, uint16_t sample)
12655 {
12656 #define	CALC_COEFF(_v, _x, _y, _z)	do {				\
12657 	int _t;								\
12658 	_t = _x - 20;							\
12659 	if (_t >= 0) {							\
12660 		_v = ((_y << (30 - _x)) + (_z >> (1 + _t))) / (_z >> _t); \
12661 	} else {							\
12662 		_v = ((_y << (30 - _x)) + (_z << (-1 - _t))) / (_z << -_t); \
12663 	}								\
12664 } while (0)
12665 #define	CALC_COEFF2(_v, _x, _y, _z)	do {				\
12666 	int _t;								\
12667 	_t = _x - 11;							\
12668 	if (_t >= 0)							\
12669 		_v = (_y << (31 - _x)) / (_z >> _t);			\
12670 	else								\
12671 		_v = (_y << (31 - _x)) / (_z << -_t);			\
12672 } while (0)
12673 	struct bwn_phy_lp_iq_est ie;
12674 	uint16_t v0, v1;
12675 	int tmp[2], ret;
12676 
12677 	v1 = BWN_PHY_READ(mac, BWN_PHY_RX_COMP_COEFF_S);
12678 	v0 = v1 >> 8;
12679 	v1 |= 0xff;
12680 
12681 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, 0x00c0);
12682 	BWN_PHY_MASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff);
12683 
12684 	ret = bwn_phy_lp_rx_iq_est(mac, sample, 32, &ie);
12685 	if (ret == 0)
12686 		goto done;
12687 
12688 	if (ie.ie_ipwr + ie.ie_qpwr < 2) {
12689 		ret = 0;
12690 		goto done;
12691 	}
12692 
12693 	CALC_COEFF(tmp[0], bwn_nbits(ie.ie_iqprod), ie.ie_iqprod, ie.ie_ipwr);
12694 	CALC_COEFF2(tmp[1], bwn_nbits(ie.ie_qpwr), ie.ie_qpwr, ie.ie_ipwr);
12695 
12696 	tmp[1] = -bwn_sqrt(mac, tmp[1] - (tmp[0] * tmp[0]));
12697 	v0 = tmp[0] >> 3;
12698 	v1 = tmp[1] >> 4;
12699 done:
12700 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0xff00, v1);
12701 	BWN_PHY_SETMASK(mac, BWN_PHY_RX_COMP_COEFF_S, 0x00ff, v0 << 8);
12702 	return ret;
12703 #undef CALC_COEFF
12704 #undef CALC_COEFF2
12705 }
12706 
12707 static void
12708 bwn_phy_lp_tblinit_r01(struct bwn_mac *mac)
12709 {
12710 	static const uint16_t noisescale[] = {
12711 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12712 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4,
12713 		0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
12714 		0xa4a4, 0xa4a4, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12715 		0x0000, 0x0000, 0x4c00, 0x2d36, 0x0000, 0x0000, 0x4c00, 0x2d36,
12716 	};
12717 	static const uint16_t crsgainnft[] = {
12718 		0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f,
12719 		0x036f, 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381,
12720 		0x0374, 0x0381, 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f,
12721 		0x0040, 0x005e, 0x007f, 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d,
12722 		0x013d,
12723 	};
12724 	static const uint16_t filterctl[] = {
12725 		0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077,
12726 		0xff53, 0x0127,
12727 	};
12728 	static const uint32_t psctl[] = {
12729 		0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101,
12730 		0x00000080, 0x08080101, 0x00000040, 0x08080101, 0x000000c0,
12731 		0x08a81501, 0x000000c0, 0x0fe8fd01, 0x000000c0, 0x08300105,
12732 		0x000000c0, 0x08080201, 0x000000c0, 0x08280205, 0x000000c0,
12733 		0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, 0x08080202,
12734 		0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
12735 		0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106,
12736 		0x000000c0, 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
12737 	};
12738 	static const uint16_t ofdmcckgain_r0[] = {
12739 		0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12740 		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12741 		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12742 		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12743 		0x755d,
12744 	};
12745 	static const uint16_t ofdmcckgain_r1[] = {
12746 		0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001,
12747 		0x5001, 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055,
12748 		0x2065, 0x2075, 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d,
12749 		0x135d, 0x055d, 0x155d, 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d,
12750 		0x755d,
12751 	};
12752 	static const uint16_t gaindelta[] = {
12753 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12754 		0x0000,
12755 	};
12756 	static const uint32_t txpwrctl[] = {
12757 		0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c,
12758 		0x0000004b, 0x0000004a, 0x00000049, 0x00000048, 0x00000047,
12759 		0x00000046, 0x00000045, 0x00000044, 0x00000043, 0x00000042,
12760 		0x00000041, 0x00000040, 0x0000003f, 0x0000003e, 0x0000003d,
12761 		0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, 0x00000038,
12762 		0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
12763 		0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e,
12764 		0x0000002d, 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029,
12765 		0x00000028, 0x00000027, 0x00000026, 0x00000025, 0x00000024,
12766 		0x00000023, 0x00000022, 0x00000021, 0x00000020, 0x0000001f,
12767 		0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, 0x0000001a,
12768 		0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
12769 		0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000,
12770 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12771 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12772 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12773 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12774 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12775 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12776 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12777 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12778 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12779 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12780 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12781 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12782 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12783 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12784 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12785 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12786 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12787 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12788 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12789 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12790 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12791 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12792 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12793 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12794 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12795 		0x00000000, 0x00000000, 0x000075a0, 0x000075a0, 0x000075a1,
12796 		0x000075a1, 0x000075a2, 0x000075a2, 0x000075a3, 0x000075a3,
12797 		0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, 0x000074b2,
12798 		0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
12799 		0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23,
12800 		0x00006d23, 0x00004660, 0x00004660, 0x00004661, 0x00004661,
12801 		0x00004662, 0x00004662, 0x00004663, 0x00004663, 0x00003e60,
12802 		0x00003e60, 0x00003e61, 0x00003e61, 0x00003e62, 0x00003e62,
12803 		0x00003e63, 0x00003e63, 0x00003660, 0x00003660, 0x00003661,
12804 		0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
12805 		0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62,
12806 		0x00002e62, 0x00002e63, 0x00002e63, 0x00002660, 0x00002660,
12807 		0x00002661, 0x00002661, 0x00002662, 0x00002662, 0x00002663,
12808 		0x00002663, 0x000025e0, 0x000025e0, 0x000025e1, 0x000025e1,
12809 		0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, 0x00001de0,
12810 		0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
12811 		0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61,
12812 		0x00001d61, 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63,
12813 		0x00001560, 0x00001560, 0x00001561, 0x00001561, 0x00001562,
12814 		0x00001562, 0x00001563, 0x00001563, 0x00000d60, 0x00000d60,
12815 		0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, 0x00000d63,
12816 		0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
12817 		0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10,
12818 		0x00000e10, 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12,
12819 		0x00000e13, 0x00000e13, 0x00000bf0, 0x00000bf0, 0x00000bf1,
12820 		0x00000bf1, 0x00000bf2, 0x00000bf2, 0x00000bf3, 0x00000bf3,
12821 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12822 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12823 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12824 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12825 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12826 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12827 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12828 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12829 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12830 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12831 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12832 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12833 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12834 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12835 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12836 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12837 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12838 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12839 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12840 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12841 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12842 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12843 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12844 		0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
12845 		0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000,
12846 		0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
12847 		0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04,
12848 		0x0000fcff, 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006,
12849 		0x0000ff03, 0x000007fc, 0x0000fc08, 0x00000203, 0x0000fffb,
12850 		0x00000600, 0x0000fa01, 0x0000fc03, 0x0000fe06, 0x0000fe00,
12851 		0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, 0x000004fd,
12852 		0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
12853 		0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa,
12854 		0x00000700, 0x00000305, 0x000004ff, 0x00000801, 0x00000503,
12855 		0x000005f9, 0x00000404, 0x0000fb08, 0x000005fd, 0x00000501,
12856 		0x00000405, 0x0000fb03, 0x000007fc, 0x00000403, 0x00000303,
12857 		0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, 0x0000fe01,
12858 		0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
12859 		0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa,
12860 		0x000003fe, 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06,
12861 		0x000008fc, 0x00000701, 0x00000504, 0x0000fdfe, 0x0000fdfc,
12862 		0x000003fe, 0x00000704, 0x000002fc, 0x000004f9, 0x0000fdfd,
12863 		0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, 0x000004f9,
12864 		0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
12865 		0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa,
12866 		0x00000305, 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc,
12867 		0x0000fe03, 0x00000701, 0x000001fb, 0x000001f9, 0x00000206,
12868 		0x000006fd, 0x00000508, 0x00000700, 0x00000304, 0x000005fe,
12869 		0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, 0x000007f9,
12870 		0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
12871 		0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb,
12872 		0x00000702,
12873 	};
12874 
12875 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
12876 
12877 	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
12878 	    bwn_tab_sigsq_tbl);
12879 	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
12880 	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(crsgainnft), crsgainnft);
12881 	bwn_tab_write_multi(mac, BWN_TAB_2(8, 0), N(filterctl), filterctl);
12882 	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(psctl), psctl);
12883 	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
12884 	    bwn_tab_pllfrac_tbl);
12885 	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
12886 	    bwn_tabl_iqlocal_tbl);
12887 	if (mac->mac_phy.rev == 0) {
12888 		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r0),
12889 		    ofdmcckgain_r0);
12890 		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r0),
12891 		    ofdmcckgain_r0);
12892 	} else {
12893 		bwn_tab_write_multi(mac, BWN_TAB_2(13, 0), N(ofdmcckgain_r1),
12894 		    ofdmcckgain_r1);
12895 		bwn_tab_write_multi(mac, BWN_TAB_2(12, 0), N(ofdmcckgain_r1),
12896 		    ofdmcckgain_r1);
12897 	}
12898 	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(gaindelta), gaindelta);
12899 	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(txpwrctl), txpwrctl);
12900 }
12901 
12902 static void
12903 bwn_phy_lp_tblinit_r2(struct bwn_mac *mac)
12904 {
12905 	struct bwn_softc *sc = mac->mac_sc;
12906 	int i;
12907 	static const uint16_t noisescale[] = {
12908 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12909 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12910 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12911 		0x00a4, 0x00a4, 0x0000, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12912 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12913 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
12914 		0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4
12915 	};
12916 	static const uint32_t filterctl[] = {
12917 		0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27,
12918 		0x0000217f, 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f
12919 	};
12920 	static const uint32_t psctl[] = {
12921 		0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000,
12922 		0x00002080, 0x00006180, 0x00003002, 0x00000040, 0x00002042,
12923 		0x00180047, 0x00080043, 0x00000041, 0x000020c1, 0x00046006,
12924 		0x00042002, 0x00040000, 0x00002003, 0x00180006, 0x00080002
12925 	};
12926 	static const uint32_t gainidx[] = {
12927 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12928 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12929 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12930 		0x00000000, 0x00000000, 0x00000000, 0x10000001, 0x00000000,
12931 		0x20000082, 0x00000000, 0x40000104, 0x00000000, 0x60004207,
12932 		0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
12933 		0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288,
12934 		0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
12935 		0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794,
12936 		0x00000010, 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011,
12937 		0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21,
12938 		0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
12939 		0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329,
12940 		0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
12941 		0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, 0x00000000,
12942 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12943 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12944 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12945 		0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082,
12946 		0x00000000, 0x40000104, 0x00000000, 0x60004207, 0x00000001,
12947 		0x7000838a, 0x00000001, 0xd021050d, 0x00000001, 0xe041c683,
12948 		0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
12949 		0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711,
12950 		0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
12951 		0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c,
12952 		0x00000018, 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019,
12953 		0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, 0xb36811a6,
12954 		0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
12955 		0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c,
12956 		0x0000001a, 0x64ca55ad, 0x0000001a
12957 	};
12958 	static const uint16_t auxgainidx[] = {
12959 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
12960 		0x0000, 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000,
12961 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002,
12962 		0x0004, 0x0016
12963 	};
12964 	static const uint16_t swctl[] = {
12965 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
12966 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
12967 		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
12968 		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
12969 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
12970 		0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028,
12971 		0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
12972 		0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018
12973 	};
12974 	static const uint8_t hf[] = {
12975 		0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
12976 		0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17
12977 	};
12978 	static const uint32_t gainval[] = {
12979 		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
12980 		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
12981 		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
12982 		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
12983 		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
12984 		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
12985 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12986 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
12987 		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
12988 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
12989 		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
12990 		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
12991 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009,
12992 		0x000000f1, 0x00000000, 0x00000000
12993 	};
12994 	static const uint16_t gain[] = {
12995 		0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808,
12996 		0x080a, 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813,
12997 		0x0814, 0x0816, 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824,
12998 		0x0830, 0x0834, 0x0837, 0x083b, 0x083f, 0x0840, 0x0844, 0x0857,
12999 		0x085b, 0x085f, 0x08d7, 0x08db, 0x08df, 0x0957, 0x095b, 0x095f,
13000 		0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, 0x175f, 0x0000, 0x0000,
13001 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13002 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13003 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13004 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13005 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13006 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13007 	};
13008 	static const uint32_t papdeps[] = {
13009 		0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9,
13010 		0x00021fdf, 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7,
13011 		0x0004efc2, 0x00055fb5, 0x0005cfb0, 0x00063fa8, 0x00068fa3,
13012 		0x00071f98, 0x0007ef92, 0x00084f8b, 0x0008df82, 0x00097f77,
13013 		0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, 0x000bff41,
13014 		0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
13015 		0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15,
13016 		0x00143f1c, 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f,
13017 		0x001e6f7e, 0x0021cfa4, 0x0025bfd2, 0x002a2008, 0x002fb047,
13018 		0x00360090, 0x003d40e0, 0x0045c135, 0x004fb189, 0x005ae1d7,
13019 		0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, 0x007ff2e3,
13020 		0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
13021 		0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506
13022 	};
13023 	static const uint32_t papdmult[] = {
13024 		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13025 		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13026 		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13027 		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13028 		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13029 		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13030 		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13031 		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13032 		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13033 		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13034 		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13035 		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13036 		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13037 	};
13038 	static const uint32_t gainidx_a0[] = {
13039 		0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060,
13040 		0x00511065, 0x004c806b, 0x0047d072, 0x00444078, 0x00400080,
13041 		0x003ca087, 0x0039408f, 0x0035e098, 0x0032e0a1, 0x003030aa,
13042 		0x002d80b4, 0x002ae0bf, 0x002880ca, 0x002640d6, 0x002410e3,
13043 		0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, 0x001b012f,
13044 		0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
13045 		0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a,
13046 		0x000e523a, 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd,
13047 		0x000ac2f8, 0x000a2325, 0x00099355, 0x00091387, 0x000883bd,
13048 		0x000813f5, 0x0007a432, 0x00073471, 0x0006c4b5, 0x000664fc,
13049 		0x00061547, 0x0005b598, 0x000565ec, 0x00051646, 0x0004d6a5,
13050 		0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
13051 		0x00036963, 0x000339f2, 0x00030a89, 0x0002db28
13052 	};
13053 	static const uint16_t auxgainidx_a0[] = {
13054 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13055 		0x0000, 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000,
13056 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13057 		0x0002, 0x0014
13058 	};
13059 	static const uint32_t gainval_a0[] = {
13060 		0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb,
13061 		0x00000004, 0x00000008, 0x0000000d, 0x00000001, 0x00000004,
13062 		0x00000007, 0x0000000a, 0x0000000d, 0x00000010, 0x00000012,
13063 		0x00000015, 0x00000000, 0x00000006, 0x0000000c, 0x00000000,
13064 		0x00000000, 0x00000000, 0x00000012, 0x00000000, 0x00000000,
13065 		0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
13066 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13067 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
13068 		0x00000000, 0x00000000, 0x0000001e, 0x00000000, 0x00000000,
13069 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003,
13070 		0x00000006, 0x00000009, 0x0000000c, 0x0000000f, 0x00000012,
13071 		0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
13072 		0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f,
13073 		0x000000f7, 0x00000000, 0x00000000
13074 	};
13075 	static const uint16_t gain_a0[] = {
13076 		0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b,
13077 		0x000c, 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016,
13078 		0x0017, 0x001a, 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034,
13079 		0x0037, 0x003b, 0x003f, 0x0040, 0x0044, 0x0057, 0x005b, 0x005f,
13080 		0x00d7, 0x00db, 0x00df, 0x0157, 0x015b, 0x015f, 0x0357, 0x035b,
13081 		0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, 0x0000, 0x0000, 0x0000,
13082 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13083 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13084 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13085 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13086 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
13087 		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
13088 	};
13089 
13090 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
13091 
13092 	for (i = 0; i < 704; i++)
13093 		bwn_tab_write(mac, BWN_TAB_4(7, i), 0);
13094 
13095 	bwn_tab_write_multi(mac, BWN_TAB_1(2, 0), N(bwn_tab_sigsq_tbl),
13096 	    bwn_tab_sigsq_tbl);
13097 	bwn_tab_write_multi(mac, BWN_TAB_2(1, 0), N(noisescale), noisescale);
13098 	bwn_tab_write_multi(mac, BWN_TAB_4(11, 0), N(filterctl), filterctl);
13099 	bwn_tab_write_multi(mac, BWN_TAB_4(12, 0), N(psctl), psctl);
13100 	bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx), gainidx);
13101 	bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx), auxgainidx);
13102 	bwn_tab_write_multi(mac, BWN_TAB_2(15, 0), N(swctl), swctl);
13103 	bwn_tab_write_multi(mac, BWN_TAB_1(16, 0), N(hf), hf);
13104 	bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval), gainval);
13105 	bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain), gain);
13106 	bwn_tab_write_multi(mac, BWN_TAB_1(6, 0), N(bwn_tab_pllfrac_tbl),
13107 	    bwn_tab_pllfrac_tbl);
13108 	bwn_tab_write_multi(mac, BWN_TAB_2(0, 0), N(bwn_tabl_iqlocal_tbl),
13109 	    bwn_tabl_iqlocal_tbl);
13110 	bwn_tab_write_multi(mac, BWN_TAB_4(9, 0), N(papdeps), papdeps);
13111 	bwn_tab_write_multi(mac, BWN_TAB_4(10, 0), N(papdmult), papdmult);
13112 
13113 	if ((siba_get_chipid(sc->sc_dev) == 0x4325) &&
13114 	    (siba_get_chiprev(sc->sc_dev) == 0)) {
13115 		bwn_tab_write_multi(mac, BWN_TAB_4(13, 0), N(gainidx_a0),
13116 		    gainidx_a0);
13117 		bwn_tab_write_multi(mac, BWN_TAB_2(14, 0), N(auxgainidx_a0),
13118 		    auxgainidx_a0);
13119 		bwn_tab_write_multi(mac, BWN_TAB_4(17, 0), N(gainval_a0),
13120 		    gainval_a0);
13121 		bwn_tab_write_multi(mac, BWN_TAB_2(18, 0), N(gain_a0), gain_a0);
13122 	}
13123 }
13124 
13125 static void
13126 bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
13127 {
13128 	struct bwn_softc *sc = mac->mac_sc;
13129 	struct ieee80211com *ic = &sc->sc_ic;
13130 	static struct bwn_txgain_entry txgain_r2[] = {
13131 		{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
13132 		{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
13133 		{ 255, 255, 203, 0, 135 }, { 255, 255, 203, 0, 131 },
13134 		{ 255, 255, 203, 0, 128 }, { 255, 255, 203, 0, 124 },
13135 		{ 255, 255, 203, 0, 121 }, { 255, 255, 203, 0, 117 },
13136 		{ 255, 255, 203, 0, 114 }, { 255, 255, 203, 0, 111 },
13137 		{ 255, 255, 203, 0, 107 }, { 255, 255, 203, 0, 104 },
13138 		{ 255, 255, 203, 0, 101 }, { 255, 255, 203, 0, 99 },
13139 		{ 255, 255, 203, 0, 96 }, { 255, 255, 203, 0, 93 },
13140 		{ 255, 255, 203, 0, 90 }, { 255, 255, 203, 0, 88 },
13141 		{ 255, 255, 203, 0, 85 }, { 255, 255, 203, 0, 83 },
13142 		{ 255, 255, 203, 0, 81 }, { 255, 255, 203, 0, 78 },
13143 		{ 255, 255, 203, 0, 76 }, { 255, 255, 203, 0, 74 },
13144 		{ 255, 255, 203, 0, 72 }, { 255, 255, 203, 0, 70 },
13145 		{ 255, 255, 203, 0, 68 }, { 255, 255, 203, 0, 66 },
13146 		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13147 		{ 255, 255, 192, 0, 64 }, { 255, 255, 186, 0, 64 },
13148 		{ 255, 255, 181, 0, 64 }, { 255, 255, 176, 0, 64 },
13149 		{ 255, 255, 171, 0, 64 }, { 255, 255, 166, 0, 64 },
13150 		{ 255, 255, 161, 0, 64 }, { 255, 255, 157, 0, 64 },
13151 		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13152 		{ 255, 255, 144, 0, 64 }, { 255, 255, 140, 0, 64 },
13153 		{ 255, 255, 136, 0, 64 }, { 255, 255, 132, 0, 64 },
13154 		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13155 		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13156 		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13157 		{ 255, 255, 108, 0, 64 }, { 255, 255, 105, 0, 64 },
13158 		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13159 		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13160 		{ 255, 255, 91, 0, 64 }, { 255, 255, 88, 0, 64 },
13161 		{ 255, 255, 86, 0, 64 }, { 255, 255, 83, 0, 64 },
13162 		{ 255, 255, 81, 0, 64 }, { 255, 255, 79, 0, 64 },
13163 		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13164 		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13165 		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13166 		{ 255, 255, 64, 0, 64 }, { 255, 248, 64, 0, 64 },
13167 		{ 255, 248, 62, 0, 64 }, { 255, 241, 62, 0, 64 },
13168 		{ 255, 241, 60, 0, 64 }, { 255, 234, 60, 0, 64 },
13169 		{ 255, 234, 59, 0, 64 }, { 255, 227, 59, 0, 64 },
13170 		{ 255, 227, 57, 0, 64 }, { 255, 221, 57, 0, 64 },
13171 		{ 255, 221, 55, 0, 64 }, { 255, 215, 55, 0, 64 },
13172 		{ 255, 215, 54, 0, 64 }, { 255, 208, 54, 0, 64 },
13173 		{ 255, 208, 52, 0, 64 }, { 255, 203, 52, 0, 64 },
13174 		{ 255, 203, 51, 0, 64 }, { 255, 197, 51, 0, 64 },
13175 		{ 255, 197, 49, 0, 64 }, { 255, 191, 49, 0, 64 },
13176 		{ 255, 191, 48, 0, 64 }, { 255, 186, 48, 0, 64 },
13177 		{ 255, 186, 47, 0, 64 }, { 255, 181, 47, 0, 64 },
13178 		{ 255, 181, 45, 0, 64 }, { 255, 175, 45, 0, 64 },
13179 		{ 255, 175, 44, 0, 64 }, { 255, 170, 44, 0, 64 },
13180 		{ 255, 170, 43, 0, 64 }, { 255, 166, 43, 0, 64 },
13181 		{ 255, 166, 42, 0, 64 }, { 255, 161, 42, 0, 64 },
13182 		{ 255, 161, 40, 0, 64 }, { 255, 156, 40, 0, 64 },
13183 		{ 255, 156, 39, 0, 64 }, { 255, 152, 39, 0, 64 },
13184 		{ 255, 152, 38, 0, 64 }, { 255, 148, 38, 0, 64 },
13185 		{ 255, 148, 37, 0, 64 }, { 255, 143, 37, 0, 64 },
13186 		{ 255, 143, 36, 0, 64 }, { 255, 139, 36, 0, 64 },
13187 		{ 255, 139, 35, 0, 64 }, { 255, 135, 35, 0, 64 },
13188 		{ 255, 135, 34, 0, 64 }, { 255, 132, 34, 0, 64 },
13189 		{ 255, 132, 33, 0, 64 }, { 255, 128, 33, 0, 64 },
13190 		{ 255, 128, 32, 0, 64 }, { 255, 124, 32, 0, 64 },
13191 		{ 255, 124, 31, 0, 64 }, { 255, 121, 31, 0, 64 },
13192 		{ 255, 121, 30, 0, 64 }, { 255, 117, 30, 0, 64 },
13193 		{ 255, 117, 29, 0, 64 }, { 255, 114, 29, 0, 64 },
13194 		{ 255, 114, 29, 0, 64 }, { 255, 111, 29, 0, 64 },
13195 	};
13196 	static struct bwn_txgain_entry txgain_2ghz_r2[] = {
13197 		{ 7, 99, 255, 0, 64 }, { 7, 96, 255, 0, 64 },
13198 		{ 7, 93, 255, 0, 64 }, { 7, 90, 255, 0, 64 },
13199 		{ 7, 88, 255, 0, 64 }, { 7, 85, 255, 0, 64 },
13200 		{ 7, 83, 255, 0, 64 }, { 7, 81, 255, 0, 64 },
13201 		{ 7, 78, 255, 0, 64 }, { 7, 76, 255, 0, 64 },
13202 		{ 7, 74, 255, 0, 64 }, { 7, 72, 255, 0, 64 },
13203 		{ 7, 70, 255, 0, 64 }, { 7, 68, 255, 0, 64 },
13204 		{ 7, 66, 255, 0, 64 }, { 7, 64, 255, 0, 64 },
13205 		{ 7, 64, 255, 0, 64 }, { 7, 62, 255, 0, 64 },
13206 		{ 7, 62, 248, 0, 64 }, { 7, 60, 248, 0, 64 },
13207 		{ 7, 60, 241, 0, 64 }, { 7, 59, 241, 0, 64 },
13208 		{ 7, 59, 234, 0, 64 }, { 7, 57, 234, 0, 64 },
13209 		{ 7, 57, 227, 0, 64 }, { 7, 55, 227, 0, 64 },
13210 		{ 7, 55, 221, 0, 64 }, { 7, 54, 221, 0, 64 },
13211 		{ 7, 54, 215, 0, 64 }, { 7, 52, 215, 0, 64 },
13212 		{ 7, 52, 208, 0, 64 }, { 7, 51, 208, 0, 64 },
13213 		{ 7, 51, 203, 0, 64 }, { 7, 49, 203, 0, 64 },
13214 		{ 7, 49, 197, 0, 64 }, { 7, 48, 197, 0, 64 },
13215 		{ 7, 48, 191, 0, 64 }, { 7, 47, 191, 0, 64 },
13216 		{ 7, 47, 186, 0, 64 }, { 7, 45, 186, 0, 64 },
13217 		{ 7, 45, 181, 0, 64 }, { 7, 44, 181, 0, 64 },
13218 		{ 7, 44, 175, 0, 64 }, { 7, 43, 175, 0, 64 },
13219 		{ 7, 43, 170, 0, 64 }, { 7, 42, 170, 0, 64 },
13220 		{ 7, 42, 166, 0, 64 }, { 7, 40, 166, 0, 64 },
13221 		{ 7, 40, 161, 0, 64 }, { 7, 39, 161, 0, 64 },
13222 		{ 7, 39, 156, 0, 64 }, { 7, 38, 156, 0, 64 },
13223 		{ 7, 38, 152, 0, 64 }, { 7, 37, 152, 0, 64 },
13224 		{ 7, 37, 148, 0, 64 }, { 7, 36, 148, 0, 64 },
13225 		{ 7, 36, 143, 0, 64 }, { 7, 35, 143, 0, 64 },
13226 		{ 7, 35, 139, 0, 64 }, { 7, 34, 139, 0, 64 },
13227 		{ 7, 34, 135, 0, 64 }, { 7, 33, 135, 0, 64 },
13228 		{ 7, 33, 132, 0, 64 }, { 7, 32, 132, 0, 64 },
13229 		{ 7, 32, 128, 0, 64 }, { 7, 31, 128, 0, 64 },
13230 		{ 7, 31, 124, 0, 64 }, { 7, 30, 124, 0, 64 },
13231 		{ 7, 30, 121, 0, 64 }, { 7, 29, 121, 0, 64 },
13232 		{ 7, 29, 117, 0, 64 }, { 7, 29, 117, 0, 64 },
13233 		{ 7, 29, 114, 0, 64 }, { 7, 28, 114, 0, 64 },
13234 		{ 7, 28, 111, 0, 64 }, { 7, 27, 111, 0, 64 },
13235 		{ 7, 27, 108, 0, 64 }, { 7, 26, 108, 0, 64 },
13236 		{ 7, 26, 104, 0, 64 }, { 7, 25, 104, 0, 64 },
13237 		{ 7, 25, 102, 0, 64 }, { 7, 25, 102, 0, 64 },
13238 		{ 7, 25, 99, 0, 64 }, { 7, 24, 99, 0, 64 },
13239 		{ 7, 24, 96, 0, 64 }, { 7, 23, 96, 0, 64 },
13240 		{ 7, 23, 93, 0, 64 }, { 7, 23, 93, 0, 64 },
13241 		{ 7, 23, 90, 0, 64 }, { 7, 22, 90, 0, 64 },
13242 		{ 7, 22, 88, 0, 64 }, { 7, 21, 88, 0, 64 },
13243 		{ 7, 21, 85, 0, 64 }, { 7, 21, 85, 0, 64 },
13244 		{ 7, 21, 83, 0, 64 }, { 7, 20, 83, 0, 64 },
13245 		{ 7, 20, 81, 0, 64 }, { 7, 20, 81, 0, 64 },
13246 		{ 7, 20, 78, 0, 64 }, { 7, 19, 78, 0, 64 },
13247 		{ 7, 19, 76, 0, 64 }, { 7, 19, 76, 0, 64 },
13248 		{ 7, 19, 74, 0, 64 }, { 7, 18, 74, 0, 64 },
13249 		{ 7, 18, 72, 0, 64 }, { 7, 18, 72, 0, 64 },
13250 		{ 7, 18, 70, 0, 64 }, { 7, 17, 70, 0, 64 },
13251 		{ 7, 17, 68, 0, 64 }, { 7, 17, 68, 0, 64 },
13252 		{ 7, 17, 66, 0, 64 }, { 7, 16, 66, 0, 64 },
13253 		{ 7, 16, 64, 0, 64 }, { 7, 16, 64, 0, 64 },
13254 		{ 7, 16, 62, 0, 64 }, { 7, 15, 62, 0, 64 },
13255 		{ 7, 15, 60, 0, 64 }, { 7, 15, 60, 0, 64 },
13256 		{ 7, 15, 59, 0, 64 }, { 7, 14, 59, 0, 64 },
13257 		{ 7, 14, 57, 0, 64 }, { 7, 14, 57, 0, 64 },
13258 		{ 7, 14, 55, 0, 64 }, { 7, 14, 55, 0, 64 },
13259 		{ 7, 14, 54, 0, 64 }, { 7, 13, 54, 0, 64 },
13260 		{ 7, 13, 52, 0, 64 }, { 7, 13, 52, 0, 64 },
13261 	};
13262 	static struct bwn_txgain_entry txgain_5ghz_r2[] = {
13263 		{ 255, 255, 255, 0, 152 }, { 255, 255, 255, 0, 147 },
13264 		{ 255, 255, 255, 0, 143 }, { 255, 255, 255, 0, 139 },
13265 		{ 255, 255, 255, 0, 135 }, { 255, 255, 255, 0, 131 },
13266 		{ 255, 255, 255, 0, 128 }, { 255, 255, 255, 0, 124 },
13267 		{ 255, 255, 255, 0, 121 }, { 255, 255, 255, 0, 117 },
13268 		{ 255, 255, 255, 0, 114 }, { 255, 255, 255, 0, 111 },
13269 		{ 255, 255, 255, 0, 107 }, { 255, 255, 255, 0, 104 },
13270 		{ 255, 255, 255, 0, 101 }, { 255, 255, 255, 0, 99 },
13271 		{ 255, 255, 255, 0, 96 }, { 255, 255, 255, 0, 93 },
13272 		{ 255, 255, 255, 0, 90 }, { 255, 255, 255, 0, 88 },
13273 		{ 255, 255, 255, 0, 85 }, { 255, 255, 255, 0, 83 },
13274 		{ 255, 255, 255, 0, 81 }, { 255, 255, 255, 0, 78 },
13275 		{ 255, 255, 255, 0, 76 }, { 255, 255, 255, 0, 74 },
13276 		{ 255, 255, 255, 0, 72 }, { 255, 255, 255, 0, 70 },
13277 		{ 255, 255, 255, 0, 68 }, { 255, 255, 255, 0, 66 },
13278 		{ 255, 255, 255, 0, 64 }, { 255, 255, 248, 0, 64 },
13279 		{ 255, 255, 241, 0, 64 }, { 255, 255, 234, 0, 64 },
13280 		{ 255, 255, 227, 0, 64 }, { 255, 255, 221, 0, 64 },
13281 		{ 255, 255, 215, 0, 64 }, { 255, 255, 208, 0, 64 },
13282 		{ 255, 255, 203, 0, 64 }, { 255, 255, 197, 0, 64 },
13283 		{ 255, 255, 191, 0, 64 }, { 255, 255, 186, 0, 64 },
13284 		{ 255, 255, 181, 0, 64 }, { 255, 255, 175, 0, 64 },
13285 		{ 255, 255, 170, 0, 64 }, { 255, 255, 166, 0, 64 },
13286 		{ 255, 255, 161, 0, 64 }, { 255, 255, 156, 0, 64 },
13287 		{ 255, 255, 152, 0, 64 }, { 255, 255, 148, 0, 64 },
13288 		{ 255, 255, 143, 0, 64 }, { 255, 255, 139, 0, 64 },
13289 		{ 255, 255, 135, 0, 64 }, { 255, 255, 132, 0, 64 },
13290 		{ 255, 255, 128, 0, 64 }, { 255, 255, 124, 0, 64 },
13291 		{ 255, 255, 121, 0, 64 }, { 255, 255, 117, 0, 64 },
13292 		{ 255, 255, 114, 0, 64 }, { 255, 255, 111, 0, 64 },
13293 		{ 255, 255, 108, 0, 64 }, { 255, 255, 104, 0, 64 },
13294 		{ 255, 255, 102, 0, 64 }, { 255, 255, 99, 0, 64 },
13295 		{ 255, 255, 96, 0, 64 }, { 255, 255, 93, 0, 64 },
13296 		{ 255, 255, 90, 0, 64 }, { 255, 255, 88, 0, 64 },
13297 		{ 255, 255, 85, 0, 64 }, { 255, 255, 83, 0, 64 },
13298 		{ 255, 255, 81, 0, 64 }, { 255, 255, 78, 0, 64 },
13299 		{ 255, 255, 76, 0, 64 }, { 255, 255, 74, 0, 64 },
13300 		{ 255, 255, 72, 0, 64 }, { 255, 255, 70, 0, 64 },
13301 		{ 255, 255, 68, 0, 64 }, { 255, 255, 66, 0, 64 },
13302 		{ 255, 255, 64, 0, 64 }, { 255, 255, 64, 0, 64 },
13303 		{ 255, 255, 62, 0, 64 }, { 255, 248, 62, 0, 64 },
13304 		{ 255, 248, 60, 0, 64 }, { 255, 241, 60, 0, 64 },
13305 		{ 255, 241, 59, 0, 64 }, { 255, 234, 59, 0, 64 },
13306 		{ 255, 234, 57, 0, 64 }, { 255, 227, 57, 0, 64 },
13307 		{ 255, 227, 55, 0, 64 }, { 255, 221, 55, 0, 64 },
13308 		{ 255, 221, 54, 0, 64 }, { 255, 215, 54, 0, 64 },
13309 		{ 255, 215, 52, 0, 64 }, { 255, 208, 52, 0, 64 },
13310 		{ 255, 208, 51, 0, 64 }, { 255, 203, 51, 0, 64 },
13311 		{ 255, 203, 49, 0, 64 }, { 255, 197, 49, 0, 64 },
13312 		{ 255, 197, 48, 0, 64 }, { 255, 191, 48, 0, 64 },
13313 		{ 255, 191, 47, 0, 64 }, { 255, 186, 47, 0, 64 },
13314 		{ 255, 186, 45, 0, 64 }, { 255, 181, 45, 0, 64 },
13315 		{ 255, 181, 44, 0, 64 }, { 255, 175, 44, 0, 64 },
13316 		{ 255, 175, 43, 0, 64 }, { 255, 170, 43, 0, 64 },
13317 		{ 255, 170, 42, 0, 64 }, { 255, 166, 42, 0, 64 },
13318 		{ 255, 166, 40, 0, 64 }, { 255, 161, 40, 0, 64 },
13319 		{ 255, 161, 39, 0, 64 }, { 255, 156, 39, 0, 64 },
13320 		{ 255, 156, 38, 0, 64 }, { 255, 152, 38, 0, 64 },
13321 		{ 255, 152, 37, 0, 64 }, { 255, 148, 37, 0, 64 },
13322 		{ 255, 148, 36, 0, 64 }, { 255, 143, 36, 0, 64 },
13323 		{ 255, 143, 35, 0, 64 }, { 255, 139, 35, 0, 64 },
13324 		{ 255, 139, 34, 0, 64 }, { 255, 135, 34, 0, 64 },
13325 		{ 255, 135, 33, 0, 64 }, { 255, 132, 33, 0, 64 },
13326 		{ 255, 132, 32, 0, 64 }, { 255, 128, 32, 0, 64 }
13327 	};
13328 	static struct bwn_txgain_entry txgain_r0[] = {
13329 		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13330 		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13331 		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13332 		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13333 		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13334 		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13335 		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13336 		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13337 		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13338 		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13339 		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13340 		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13341 		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13342 		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13343 		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13344 		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13345 		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13346 		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13347 		{ 7, 15, 13, 0, 70 }, { 7, 15, 13, 0, 68 },
13348 		{ 7, 15, 13, 0, 66 }, { 7, 15, 13, 0, 64 },
13349 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13350 		{ 7, 15, 13, 0, 59 }, { 7, 15, 13, 0, 57 },
13351 		{ 7, 15, 12, 0, 71 }, { 7, 15, 12, 0, 69 },
13352 		{ 7, 15, 12, 0, 67 }, { 7, 15, 12, 0, 65 },
13353 		{ 7, 15, 12, 0, 63 }, { 7, 15, 12, 0, 62 },
13354 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 58 },
13355 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 70 },
13356 		{ 7, 15, 11, 0, 68 }, { 7, 15, 11, 0, 66 },
13357 		{ 7, 15, 11, 0, 65 }, { 7, 15, 11, 0, 63 },
13358 		{ 7, 15, 11, 0, 61 }, { 7, 15, 11, 0, 59 },
13359 		{ 7, 15, 11, 0, 58 }, { 7, 15, 10, 0, 71 },
13360 		{ 7, 15, 10, 0, 69 }, { 7, 15, 10, 0, 67 },
13361 		{ 7, 15, 10, 0, 65 }, { 7, 15, 10, 0, 63 },
13362 		{ 7, 15, 10, 0, 61 }, { 7, 15, 10, 0, 60 },
13363 		{ 7, 15, 10, 0, 58 }, { 7, 15, 10, 0, 56 },
13364 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13365 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13366 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 60 },
13367 		{ 7, 15, 9, 0, 59 }, { 7, 14, 9, 0, 72 },
13368 		{ 7, 14, 9, 0, 70 }, { 7, 14, 9, 0, 68 },
13369 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 64 },
13370 		{ 7, 14, 9, 0, 62 }, { 7, 14, 9, 0, 60 },
13371 		{ 7, 14, 9, 0, 59 }, { 7, 13, 9, 0, 72 },
13372 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13373 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13374 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13375 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13376 		{ 7, 13, 8, 0, 72 }, { 7, 13, 8, 0, 70 },
13377 		{ 7, 13, 8, 0, 68 }, { 7, 13, 8, 0, 66 },
13378 		{ 7, 13, 8, 0, 64 }, { 7, 13, 8, 0, 62 },
13379 		{ 7, 13, 8, 0, 60 }, { 7, 13, 8, 0, 59 },
13380 		{ 7, 12, 8, 0, 72 }, { 7, 12, 8, 0, 70 },
13381 		{ 7, 12, 8, 0, 68 }, { 7, 12, 8, 0, 66 },
13382 		{ 7, 12, 8, 0, 64 }, { 7, 12, 8, 0, 62 },
13383 		{ 7, 12, 8, 0, 61 }, { 7, 12, 8, 0, 59 },
13384 		{ 7, 12, 7, 0, 73 }, { 7, 12, 7, 0, 71 },
13385 		{ 7, 12, 7, 0, 69 }, { 7, 12, 7, 0, 67 },
13386 		{ 7, 12, 7, 0, 65 }, { 7, 12, 7, 0, 63 },
13387 		{ 7, 12, 7, 0, 61 }, { 7, 12, 7, 0, 59 },
13388 		{ 7, 11, 7, 0, 72 }, { 7, 11, 7, 0, 70 },
13389 		{ 7, 11, 7, 0, 68 }, { 7, 11, 7, 0, 66 },
13390 		{ 7, 11, 7, 0, 65 }, { 7, 11, 7, 0, 63 },
13391 		{ 7, 11, 7, 0, 61 }, { 7, 11, 7, 0, 59 },
13392 		{ 7, 11, 6, 0, 73 }, { 7, 11, 6, 0, 71 }
13393 	};
13394 	static struct bwn_txgain_entry txgain_2ghz_r0[] = {
13395 		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13396 		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13397 		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13398 		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13399 		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13400 		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13401 		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13402 		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13403 		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13404 		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13405 		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13406 		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13407 		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13408 		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13409 		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13410 		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13411 		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13412 		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13413 		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13414 		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13415 		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13416 		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13417 		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13418 		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13419 		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13420 		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13421 		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13422 		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13423 		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13424 		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13425 		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13426 		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13427 		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13428 		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 },
13429 		{ 4, 10, 6, 0, 59 }, { 4, 10, 5, 0, 72 },
13430 		{ 4, 10, 5, 0, 70 }, { 4, 10, 5, 0, 68 },
13431 		{ 4, 10, 5, 0, 66 }, { 4, 10, 5, 0, 64 },
13432 		{ 4, 10, 5, 0, 62 }, { 4, 10, 5, 0, 60 },
13433 		{ 4, 10, 5, 0, 59 }, { 4, 9, 5, 0, 70 },
13434 		{ 4, 9, 5, 0, 68 }, { 4, 9, 5, 0, 66 },
13435 		{ 4, 9, 5, 0, 64 }, { 4, 9, 5, 0, 63 },
13436 		{ 4, 9, 5, 0, 61 }, { 4, 9, 5, 0, 59 },
13437 		{ 4, 9, 4, 0, 71 }, { 4, 9, 4, 0, 69 },
13438 		{ 4, 9, 4, 0, 67 }, { 4, 9, 4, 0, 65 },
13439 		{ 4, 9, 4, 0, 63 }, { 4, 9, 4, 0, 62 },
13440 		{ 4, 9, 4, 0, 60 }, { 4, 9, 4, 0, 58 },
13441 		{ 4, 8, 4, 0, 70 }, { 4, 8, 4, 0, 68 },
13442 		{ 4, 8, 4, 0, 66 }, { 4, 8, 4, 0, 65 },
13443 		{ 4, 8, 4, 0, 63 }, { 4, 8, 4, 0, 61 },
13444 		{ 4, 8, 4, 0, 59 }, { 4, 7, 4, 0, 68 },
13445 		{ 4, 7, 4, 0, 66 }, { 4, 7, 4, 0, 64 },
13446 		{ 4, 7, 4, 0, 62 }, { 4, 7, 4, 0, 61 },
13447 		{ 4, 7, 4, 0, 59 }, { 4, 7, 3, 0, 67 },
13448 		{ 4, 7, 3, 0, 65 }, { 4, 7, 3, 0, 63 },
13449 		{ 4, 7, 3, 0, 62 }, { 4, 7, 3, 0, 60 },
13450 		{ 4, 6, 3, 0, 65 }, { 4, 6, 3, 0, 63 },
13451 		{ 4, 6, 3, 0, 61 }, { 4, 6, 3, 0, 60 },
13452 		{ 4, 6, 3, 0, 58 }, { 4, 5, 3, 0, 68 },
13453 		{ 4, 5, 3, 0, 66 }, { 4, 5, 3, 0, 64 },
13454 		{ 4, 5, 3, 0, 62 }, { 4, 5, 3, 0, 60 },
13455 		{ 4, 5, 3, 0, 59 }, { 4, 5, 3, 0, 57 },
13456 		{ 4, 4, 2, 0, 83 }, { 4, 4, 2, 0, 81 },
13457 		{ 4, 4, 2, 0, 78 }, { 4, 4, 2, 0, 76 },
13458 		{ 4, 4, 2, 0, 74 }, { 4, 4, 2, 0, 72 }
13459 	};
13460 	static struct bwn_txgain_entry txgain_5ghz_r0[] = {
13461 		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13462 		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13463 		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13464 		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13465 		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13466 		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13467 		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13468 		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13469 		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13470 		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13471 		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13472 		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13473 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13474 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13475 		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13476 		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13477 		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13478 		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13479 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13480 		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13481 		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13482 		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13483 		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13484 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13485 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13486 		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13487 		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13488 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13489 		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13490 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13491 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13492 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13493 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13494 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13495 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13496 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13497 		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13498 		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13499 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13500 		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13501 		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13502 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13503 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13504 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13505 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13506 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13507 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13508 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13509 		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13510 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13511 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13512 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13513 		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13514 		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13515 		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13516 		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13517 		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13518 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13519 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13520 		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13521 		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13522 		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13523 		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13524 		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13525 	};
13526 	static struct bwn_txgain_entry txgain_r1[] = {
13527 		{ 7, 15, 14, 0, 152 }, { 7, 15, 14, 0, 147 },
13528 		{ 7, 15, 14, 0, 143 }, { 7, 15, 14, 0, 139 },
13529 		{ 7, 15, 14, 0, 135 }, { 7, 15, 14, 0, 131 },
13530 		{ 7, 15, 14, 0, 128 }, { 7, 15, 14, 0, 124 },
13531 		{ 7, 15, 14, 0, 121 }, { 7, 15, 14, 0, 117 },
13532 		{ 7, 15, 14, 0, 114 }, { 7, 15, 14, 0, 111 },
13533 		{ 7, 15, 14, 0, 107 }, { 7, 15, 14, 0, 104 },
13534 		{ 7, 15, 14, 0, 101 }, { 7, 15, 14, 0, 99 },
13535 		{ 7, 15, 14, 0, 96 }, { 7, 15, 14, 0, 93 },
13536 		{ 7, 15, 14, 0, 90 }, { 7, 15, 14, 0, 88 },
13537 		{ 7, 15, 14, 0, 85 }, { 7, 15, 14, 0, 83 },
13538 		{ 7, 15, 14, 0, 81 }, { 7, 15, 14, 0, 78 },
13539 		{ 7, 15, 14, 0, 76 }, { 7, 15, 14, 0, 74 },
13540 		{ 7, 15, 14, 0, 72 }, { 7, 15, 14, 0, 70 },
13541 		{ 7, 15, 14, 0, 68 }, { 7, 15, 14, 0, 66 },
13542 		{ 7, 15, 14, 0, 64 }, { 7, 15, 14, 0, 62 },
13543 		{ 7, 15, 14, 0, 60 }, { 7, 15, 14, 0, 59 },
13544 		{ 7, 15, 14, 0, 57 }, { 7, 15, 13, 0, 72 },
13545 		{ 7, 15, 13, 0, 70 }, { 7, 15, 14, 0, 68 },
13546 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13547 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13548 		{ 7, 15, 14, 0, 59 }, { 7, 15, 14, 0, 57 },
13549 		{ 7, 15, 13, 0, 72 }, { 7, 15, 13, 0, 70 },
13550 		{ 7, 15, 13, 0, 68 }, { 7, 15, 13, 0, 66 },
13551 		{ 7, 15, 13, 0, 64 }, { 7, 15, 13, 0, 62 },
13552 		{ 7, 15, 13, 0, 60 }, { 7, 15, 13, 0, 59 },
13553 		{ 7, 15, 13, 0, 57 }, { 7, 15, 12, 0, 71 },
13554 		{ 7, 15, 12, 0, 69 }, { 7, 15, 12, 0, 67 },
13555 		{ 7, 15, 12, 0, 65 }, { 7, 15, 12, 0, 63 },
13556 		{ 7, 15, 12, 0, 62 }, { 7, 15, 12, 0, 60 },
13557 		{ 7, 15, 12, 0, 58 }, { 7, 15, 12, 0, 57 },
13558 		{ 7, 15, 11, 0, 70 }, { 7, 15, 11, 0, 68 },
13559 		{ 7, 15, 11, 0, 66 }, { 7, 15, 11, 0, 65 },
13560 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13561 		{ 7, 15, 11, 0, 59 }, { 7, 15, 11, 0, 58 },
13562 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13563 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13564 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13565 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13566 		{ 7, 15, 10, 0, 56 }, { 7, 15, 9, 0, 70 },
13567 		{ 7, 15, 9, 0, 68 }, { 7, 15, 9, 0, 66 },
13568 		{ 7, 15, 9, 0, 64 }, { 7, 15, 9, 0, 62 },
13569 		{ 7, 15, 9, 0, 60 }, { 7, 15, 9, 0, 59 },
13570 		{ 7, 14, 9, 0, 72 }, { 7, 14, 9, 0, 70 },
13571 		{ 7, 14, 9, 0, 68 }, { 7, 14, 9, 0, 66 },
13572 		{ 7, 14, 9, 0, 64 }, { 7, 14, 9, 0, 62 },
13573 		{ 7, 14, 9, 0, 60 }, { 7, 14, 9, 0, 59 },
13574 		{ 7, 13, 9, 0, 72 }, { 7, 13, 9, 0, 70 },
13575 		{ 7, 13, 9, 0, 68 }, { 7, 13, 9, 0, 66 },
13576 		{ 7, 13, 9, 0, 64 }, { 7, 13, 9, 0, 63 },
13577 		{ 7, 13, 9, 0, 61 }, { 7, 13, 9, 0, 59 },
13578 		{ 7, 13, 9, 0, 57 }, { 7, 13, 8, 0, 72 },
13579 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13580 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13581 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13582 		{ 7, 13, 8, 0, 59 }, { 7, 12, 8, 0, 72 },
13583 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13584 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13585 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13586 		{ 7, 12, 8, 0, 59 }, { 7, 12, 7, 0, 73 },
13587 		{ 7, 12, 7, 0, 71 }, { 7, 12, 7, 0, 69 },
13588 		{ 7, 12, 7, 0, 67 }, { 7, 12, 7, 0, 65 },
13589 		{ 7, 12, 7, 0, 63 }, { 7, 12, 7, 0, 61 },
13590 		{ 7, 12, 7, 0, 59 }, { 7, 11, 7, 0, 72 },
13591 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13592 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 65 },
13593 		{ 7, 11, 7, 0, 63 }, { 7, 11, 7, 0, 61 },
13594 		{ 7, 11, 7, 0, 59 }, { 7, 11, 6, 0, 73 },
13595 		{ 7, 11, 6, 0, 71 }
13596 	};
13597 	static struct bwn_txgain_entry txgain_2ghz_r1[] = {
13598 		{ 4, 15, 15, 0, 90 }, { 4, 15, 15, 0, 88 },
13599 		{ 4, 15, 15, 0, 85 }, { 4, 15, 15, 0, 83 },
13600 		{ 4, 15, 15, 0, 81 }, { 4, 15, 15, 0, 78 },
13601 		{ 4, 15, 15, 0, 76 }, { 4, 15, 15, 0, 74 },
13602 		{ 4, 15, 15, 0, 72 }, { 4, 15, 15, 0, 70 },
13603 		{ 4, 15, 15, 0, 68 }, { 4, 15, 15, 0, 66 },
13604 		{ 4, 15, 15, 0, 64 }, { 4, 15, 15, 0, 62 },
13605 		{ 4, 15, 15, 0, 60 }, { 4, 15, 15, 0, 59 },
13606 		{ 4, 15, 14, 0, 72 }, { 4, 15, 14, 0, 70 },
13607 		{ 4, 15, 14, 0, 68 }, { 4, 15, 14, 0, 66 },
13608 		{ 4, 15, 14, 0, 64 }, { 4, 15, 14, 0, 62 },
13609 		{ 4, 15, 14, 0, 60 }, { 4, 15, 14, 0, 59 },
13610 		{ 4, 15, 13, 0, 72 }, { 4, 15, 13, 0, 70 },
13611 		{ 4, 15, 13, 0, 68 }, { 4, 15, 13, 0, 66 },
13612 		{ 4, 15, 13, 0, 64 }, { 4, 15, 13, 0, 62 },
13613 		{ 4, 15, 13, 0, 60 }, { 4, 15, 13, 0, 59 },
13614 		{ 4, 15, 12, 0, 72 }, { 4, 15, 12, 0, 70 },
13615 		{ 4, 15, 12, 0, 68 }, { 4, 15, 12, 0, 66 },
13616 		{ 4, 15, 12, 0, 64 }, { 4, 15, 12, 0, 62 },
13617 		{ 4, 15, 12, 0, 60 }, { 4, 15, 12, 0, 59 },
13618 		{ 4, 15, 11, 0, 72 }, { 4, 15, 11, 0, 70 },
13619 		{ 4, 15, 11, 0, 68 }, { 4, 15, 11, 0, 66 },
13620 		{ 4, 15, 11, 0, 64 }, { 4, 15, 11, 0, 62 },
13621 		{ 4, 15, 11, 0, 60 }, { 4, 15, 11, 0, 59 },
13622 		{ 4, 15, 10, 0, 72 }, { 4, 15, 10, 0, 70 },
13623 		{ 4, 15, 10, 0, 68 }, { 4, 15, 10, 0, 66 },
13624 		{ 4, 15, 10, 0, 64 }, { 4, 15, 10, 0, 62 },
13625 		{ 4, 15, 10, 0, 60 }, { 4, 15, 10, 0, 59 },
13626 		{ 4, 15, 9, 0, 72 }, { 4, 15, 9, 0, 70 },
13627 		{ 4, 15, 9, 0, 68 }, { 4, 15, 9, 0, 66 },
13628 		{ 4, 15, 9, 0, 64 }, { 4, 15, 9, 0, 62 },
13629 		{ 4, 15, 9, 0, 60 }, { 4, 15, 9, 0, 59 },
13630 		{ 4, 14, 9, 0, 72 }, { 4, 14, 9, 0, 70 },
13631 		{ 4, 14, 9, 0, 68 }, { 4, 14, 9, 0, 66 },
13632 		{ 4, 14, 9, 0, 64 }, { 4, 14, 9, 0, 62 },
13633 		{ 4, 14, 9, 0, 60 }, { 4, 14, 9, 0, 59 },
13634 		{ 4, 13, 9, 0, 72 }, { 4, 13, 9, 0, 70 },
13635 		{ 4, 13, 9, 0, 68 }, { 4, 13, 9, 0, 66 },
13636 		{ 4, 13, 9, 0, 64 }, { 4, 13, 9, 0, 63 },
13637 		{ 4, 13, 9, 0, 61 }, { 4, 13, 9, 0, 59 },
13638 		{ 4, 13, 9, 0, 57 }, { 4, 13, 8, 0, 72 },
13639 		{ 4, 13, 8, 0, 70 }, { 4, 13, 8, 0, 68 },
13640 		{ 4, 13, 8, 0, 66 }, { 4, 13, 8, 0, 64 },
13641 		{ 4, 13, 8, 0, 62 }, { 4, 13, 8, 0, 60 },
13642 		{ 4, 13, 8, 0, 59 }, { 4, 12, 8, 0, 72 },
13643 		{ 4, 12, 8, 0, 70 }, { 4, 12, 8, 0, 68 },
13644 		{ 4, 12, 8, 0, 66 }, { 4, 12, 8, 0, 64 },
13645 		{ 4, 12, 8, 0, 62 }, { 4, 12, 8, 0, 61 },
13646 		{ 4, 12, 8, 0, 59 }, { 4, 12, 7, 0, 73 },
13647 		{ 4, 12, 7, 0, 71 }, { 4, 12, 7, 0, 69 },
13648 		{ 4, 12, 7, 0, 67 }, { 4, 12, 7, 0, 65 },
13649 		{ 4, 12, 7, 0, 63 }, { 4, 12, 7, 0, 61 },
13650 		{ 4, 12, 7, 0, 59 }, { 4, 11, 7, 0, 72 },
13651 		{ 4, 11, 7, 0, 70 }, { 4, 11, 7, 0, 68 },
13652 		{ 4, 11, 7, 0, 66 }, { 4, 11, 7, 0, 65 },
13653 		{ 4, 11, 7, 0, 63 }, { 4, 11, 7, 0, 61 },
13654 		{ 4, 11, 7, 0, 59 }, { 4, 11, 6, 0, 73 },
13655 		{ 4, 11, 6, 0, 71 }, { 4, 11, 6, 0, 69 },
13656 		{ 4, 11, 6, 0, 67 }, { 4, 11, 6, 0, 65 },
13657 		{ 4, 11, 6, 0, 63 }, { 4, 11, 6, 0, 61 },
13658 		{ 4, 11, 6, 0, 60 }, { 4, 10, 6, 0, 72 },
13659 		{ 4, 10, 6, 0, 70 }, { 4, 10, 6, 0, 68 },
13660 		{ 4, 10, 6, 0, 66 }, { 4, 10, 6, 0, 64 },
13661 		{ 4, 10, 6, 0, 62 }, { 4, 10, 6, 0, 60 }
13662 	};
13663 	static struct bwn_txgain_entry txgain_5ghz_r1[] = {
13664 		{ 7, 15, 15, 0, 99 }, { 7, 15, 15, 0, 96 },
13665 		{ 7, 15, 15, 0, 93 }, { 7, 15, 15, 0, 90 },
13666 		{ 7, 15, 15, 0, 88 }, { 7, 15, 15, 0, 85 },
13667 		{ 7, 15, 15, 0, 83 }, { 7, 15, 15, 0, 81 },
13668 		{ 7, 15, 15, 0, 78 }, { 7, 15, 15, 0, 76 },
13669 		{ 7, 15, 15, 0, 74 }, { 7, 15, 15, 0, 72 },
13670 		{ 7, 15, 15, 0, 70 }, { 7, 15, 15, 0, 68 },
13671 		{ 7, 15, 15, 0, 66 }, { 7, 15, 15, 0, 64 },
13672 		{ 7, 15, 15, 0, 62 }, { 7, 15, 15, 0, 60 },
13673 		{ 7, 15, 15, 0, 59 }, { 7, 15, 15, 0, 57 },
13674 		{ 7, 15, 15, 0, 55 }, { 7, 15, 14, 0, 72 },
13675 		{ 7, 15, 14, 0, 70 }, { 7, 15, 14, 0, 68 },
13676 		{ 7, 15, 14, 0, 66 }, { 7, 15, 14, 0, 64 },
13677 		{ 7, 15, 14, 0, 62 }, { 7, 15, 14, 0, 60 },
13678 		{ 7, 15, 14, 0, 58 }, { 7, 15, 14, 0, 56 },
13679 		{ 7, 15, 14, 0, 55 }, { 7, 15, 13, 0, 71 },
13680 		{ 7, 15, 13, 0, 69 }, { 7, 15, 13, 0, 67 },
13681 		{ 7, 15, 13, 0, 65 }, { 7, 15, 13, 0, 63 },
13682 		{ 7, 15, 13, 0, 62 }, { 7, 15, 13, 0, 60 },
13683 		{ 7, 15, 13, 0, 58 }, { 7, 15, 13, 0, 56 },
13684 		{ 7, 15, 12, 0, 72 }, { 7, 15, 12, 0, 70 },
13685 		{ 7, 15, 12, 0, 68 }, { 7, 15, 12, 0, 66 },
13686 		{ 7, 15, 12, 0, 64 }, { 7, 15, 12, 0, 62 },
13687 		{ 7, 15, 12, 0, 60 }, { 7, 15, 12, 0, 59 },
13688 		{ 7, 15, 12, 0, 57 }, { 7, 15, 11, 0, 73 },
13689 		{ 7, 15, 11, 0, 71 }, { 7, 15, 11, 0, 69 },
13690 		{ 7, 15, 11, 0, 67 }, { 7, 15, 11, 0, 65 },
13691 		{ 7, 15, 11, 0, 63 }, { 7, 15, 11, 0, 61 },
13692 		{ 7, 15, 11, 0, 60 }, { 7, 15, 11, 0, 58 },
13693 		{ 7, 15, 10, 0, 71 }, { 7, 15, 10, 0, 69 },
13694 		{ 7, 15, 10, 0, 67 }, { 7, 15, 10, 0, 65 },
13695 		{ 7, 15, 10, 0, 63 }, { 7, 15, 10, 0, 61 },
13696 		{ 7, 15, 10, 0, 60 }, { 7, 15, 10, 0, 58 },
13697 		{ 7, 15, 9, 0, 70 }, { 7, 15, 9, 0, 68 },
13698 		{ 7, 15, 9, 0, 66 }, { 7, 15, 9, 0, 64 },
13699 		{ 7, 15, 9, 0, 62 }, { 7, 15, 9, 0, 61 },
13700 		{ 7, 15, 9, 0, 59 }, { 7, 15, 9, 0, 57 },
13701 		{ 7, 15, 9, 0, 56 }, { 7, 14, 9, 0, 68 },
13702 		{ 7, 14, 9, 0, 66 }, { 7, 14, 9, 0, 65 },
13703 		{ 7, 14, 9, 0, 63 }, { 7, 14, 9, 0, 61 },
13704 		{ 7, 14, 9, 0, 59 }, { 7, 14, 9, 0, 58 },
13705 		{ 7, 13, 9, 0, 70 }, { 7, 13, 9, 0, 68 },
13706 		{ 7, 13, 9, 0, 66 }, { 7, 13, 9, 0, 64 },
13707 		{ 7, 13, 9, 0, 63 }, { 7, 13, 9, 0, 61 },
13708 		{ 7, 13, 9, 0, 59 }, { 7, 13, 9, 0, 57 },
13709 		{ 7, 13, 8, 0, 70 }, { 7, 13, 8, 0, 68 },
13710 		{ 7, 13, 8, 0, 66 }, { 7, 13, 8, 0, 64 },
13711 		{ 7, 13, 8, 0, 62 }, { 7, 13, 8, 0, 60 },
13712 		{ 7, 13, 8, 0, 59 }, { 7, 13, 8, 0, 57 },
13713 		{ 7, 12, 8, 0, 70 }, { 7, 12, 8, 0, 68 },
13714 		{ 7, 12, 8, 0, 66 }, { 7, 12, 8, 0, 64 },
13715 		{ 7, 12, 8, 0, 62 }, { 7, 12, 8, 0, 61 },
13716 		{ 7, 12, 8, 0, 59 }, { 7, 12, 8, 0, 57 },
13717 		{ 7, 12, 7, 0, 70 }, { 7, 12, 7, 0, 68 },
13718 		{ 7, 12, 7, 0, 66 }, { 7, 12, 7, 0, 64 },
13719 		{ 7, 12, 7, 0, 62 }, { 7, 12, 7, 0, 61 },
13720 		{ 7, 12, 7, 0, 59 }, { 7, 12, 7, 0, 57 },
13721 		{ 7, 11, 7, 0, 70 }, { 7, 11, 7, 0, 68 },
13722 		{ 7, 11, 7, 0, 66 }, { 7, 11, 7, 0, 64 },
13723 		{ 7, 11, 7, 0, 62 }, { 7, 11, 7, 0, 61 },
13724 		{ 7, 11, 7, 0, 59 }, { 7, 11, 7, 0, 57 },
13725 		{ 7, 11, 6, 0, 69 }, { 7, 11, 6, 0, 67 },
13726 		{ 7, 11, 6, 0, 65 }, { 7, 11, 6, 0, 63 },
13727 		{ 7, 11, 6, 0, 62 }, { 7, 11, 6, 0, 60 }
13728 	};
13729 
13730 	if (mac->mac_phy.rev != 0 && mac->mac_phy.rev != 1) {
13731 		if (siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA)
13732 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r2);
13733 		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13734 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13735 			    txgain_2ghz_r2);
13736 		else
13737 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13738 			    txgain_5ghz_r2);
13739 		return;
13740 	}
13741 
13742 	if (mac->mac_phy.rev == 0) {
13743 		if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13744 		    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13745 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r0);
13746 		else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13747 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13748 			    txgain_2ghz_r0);
13749 		else
13750 			bwn_phy_lp_gaintbl_write_multi(mac, 0, 128,
13751 			    txgain_5ghz_r0);
13752 		return;
13753 	}
13754 
13755 	if ((siba_sprom_get_bf_hi(sc->sc_dev) & BWN_BFH_NOPA) ||
13756 	    (siba_sprom_get_bf_lo(sc->sc_dev) & BWN_BFL_HGPA))
13757 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_r1);
13758 	else if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
13759 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_2ghz_r1);
13760 	else
13761 		bwn_phy_lp_gaintbl_write_multi(mac, 0, 128, txgain_5ghz_r1);
13762 }
13763 
13764 static void
13765 bwn_tab_write(struct bwn_mac *mac, uint32_t typeoffset, uint32_t value)
13766 {
13767 	uint32_t offset, type;
13768 
13769 	type = BWN_TAB_GETTYPE(typeoffset);
13770 	offset = BWN_TAB_GETOFFSET(typeoffset);
13771 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13772 
13773 	switch (type) {
13774 	case BWN_TAB_8BIT:
13775 		KASSERT(!(value & ~0xff), ("%s:%d: fail", __func__, __LINE__));
13776 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13777 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13778 		break;
13779 	case BWN_TAB_16BIT:
13780 		KASSERT(!(value & ~0xffff),
13781 		    ("%s:%d: fail", __func__, __LINE__));
13782 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13783 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13784 		break;
13785 	case BWN_TAB_32BIT:
13786 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13787 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATAHI, value >> 16);
13788 		BWN_PHY_WRITE(mac, BWN_PHY_TABLEDATALO, value);
13789 		break;
13790 	default:
13791 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13792 	}
13793 }
13794 
13795 static int
13796 bwn_phy_lp_loopback(struct bwn_mac *mac)
13797 {
13798 	struct bwn_phy_lp_iq_est ie;
13799 	int i, index = -1;
13800 	uint32_t tmp;
13801 
13802 	memset(&ie, 0, sizeof(ie));
13803 
13804 	bwn_phy_lp_set_trsw_over(mac, 1, 1);
13805 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 1);
13806 	BWN_PHY_MASK(mac, BWN_PHY_AFE_CTL_OVRVAL, 0xfffe);
13807 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x800);
13808 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x800);
13809 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x8);
13810 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x8);
13811 	BWN_RF_WRITE(mac, BWN_B2062_N_TXCTL_A, 0x80);
13812 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_0, 0x80);
13813 	BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_VAL_0, 0x80);
13814 	for (i = 0; i < 32; i++) {
13815 		bwn_phy_lp_set_rxgain_idx(mac, i);
13816 		bwn_phy_lp_ddfs_turnon(mac, 1, 1, 5, 5, 0);
13817 		if (!(bwn_phy_lp_rx_iq_est(mac, 1000, 32, &ie)))
13818 			continue;
13819 		tmp = (ie.ie_ipwr + ie.ie_qpwr) / 1000;
13820 		if ((tmp > 4000) && (tmp < 10000)) {
13821 			index = i;
13822 			break;
13823 		}
13824 	}
13825 	bwn_phy_lp_ddfs_turnoff(mac);
13826 	return (index);
13827 }
13828 
13829 static void
13830 bwn_phy_lp_set_rxgain_idx(struct bwn_mac *mac, uint16_t idx)
13831 {
13832 
13833 	bwn_phy_lp_set_rxgain(mac, bwn_tab_read(mac, BWN_TAB_2(12, idx)));
13834 }
13835 
13836 static void
13837 bwn_phy_lp_ddfs_turnon(struct bwn_mac *mac, int i_on, int q_on,
13838     int incr1, int incr2, int scale_idx)
13839 {
13840 
13841 	bwn_phy_lp_ddfs_turnoff(mac);
13842 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0xff80);
13843 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS_POINTER_INIT, 0x80ff);
13844 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0xff80, incr1);
13845 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS_INCR_INIT, 0x80ff, incr2 << 8);
13846 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xfff7, i_on << 3);
13847 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xffef, q_on << 4);
13848 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DDFS, 0xff9f, scale_idx << 5);
13849 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffb);
13850 	BWN_PHY_SET(mac, BWN_PHY_AFE_DDFS, 0x2);
13851 	BWN_PHY_SET(mac, BWN_PHY_LP_PHY_CTL, 0x20);
13852 }
13853 
13854 static uint8_t
13855 bwn_phy_lp_rx_iq_est(struct bwn_mac *mac, uint16_t sample, uint8_t time,
13856     struct bwn_phy_lp_iq_est *ie)
13857 {
13858 	int i;
13859 
13860 	BWN_PHY_MASK(mac, BWN_PHY_CRSGAIN_CTL, 0xfff7);
13861 	BWN_PHY_WRITE(mac, BWN_PHY_IQ_NUM_SMPLS_ADDR, sample);
13862 	BWN_PHY_SETMASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xff00, time);
13863 	BWN_PHY_MASK(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xfeff);
13864 	BWN_PHY_SET(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
13865 
13866 	for (i = 0; i < 500; i++) {
13867 		if (!(BWN_PHY_READ(mac,
13868 		    BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
13869 			break;
13870 		DELAY(1000);
13871 	}
13872 	if ((BWN_PHY_READ(mac, BWN_PHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
13873 		BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
13874 		return 0;
13875 	}
13876 
13877 	ie->ie_iqprod = BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_HI_ADDR);
13878 	ie->ie_iqprod <<= 16;
13879 	ie->ie_iqprod |= BWN_PHY_READ(mac, BWN_PHY_IQ_ACC_LO_ADDR);
13880 	ie->ie_ipwr = BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_HI_ADDR);
13881 	ie->ie_ipwr <<= 16;
13882 	ie->ie_ipwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_I_PWR_ACC_LO_ADDR);
13883 	ie->ie_qpwr = BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_HI_ADDR);
13884 	ie->ie_qpwr <<= 16;
13885 	ie->ie_qpwr |= BWN_PHY_READ(mac, BWN_PHY_IQ_Q_PWR_ACC_LO_ADDR);
13886 
13887 	BWN_PHY_SET(mac, BWN_PHY_CRSGAIN_CTL, 0x8);
13888 	return 1;
13889 }
13890 
13891 static uint32_t
13892 bwn_tab_read(struct bwn_mac *mac, uint32_t typeoffset)
13893 {
13894 	uint32_t offset, type, value;
13895 
13896 	type = BWN_TAB_GETTYPE(typeoffset);
13897 	offset = BWN_TAB_GETOFFSET(typeoffset);
13898 	KASSERT(offset <= 0xffff, ("%s:%d: fail", __func__, __LINE__));
13899 
13900 	switch (type) {
13901 	case BWN_TAB_8BIT:
13902 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13903 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO) & 0xff;
13904 		break;
13905 	case BWN_TAB_16BIT:
13906 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13907 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
13908 		break;
13909 	case BWN_TAB_32BIT:
13910 		BWN_PHY_WRITE(mac, BWN_PHY_TABLE_ADDR, offset);
13911 		value = BWN_PHY_READ(mac, BWN_PHY_TABLEDATAHI);
13912 		value <<= 16;
13913 		value |= BWN_PHY_READ(mac, BWN_PHY_TABLEDATALO);
13914 		break;
13915 	default:
13916 		KASSERT(0 == 1, ("%s:%d: fail", __func__, __LINE__));
13917 		value = 0;
13918 	}
13919 
13920 	return (value);
13921 }
13922 
13923 static void
13924 bwn_phy_lp_ddfs_turnoff(struct bwn_mac *mac)
13925 {
13926 
13927 	BWN_PHY_MASK(mac, BWN_PHY_AFE_DDFS, 0xfffd);
13928 	BWN_PHY_MASK(mac, BWN_PHY_LP_PHY_CTL, 0xffdf);
13929 }
13930 
13931 static void
13932 bwn_phy_lp_set_txgain_dac(struct bwn_mac *mac, uint16_t dac)
13933 {
13934 	uint16_t ctl;
13935 
13936 	ctl = BWN_PHY_READ(mac, BWN_PHY_AFE_DAC_CTL) & 0xc7f;
13937 	ctl |= dac << 7;
13938 	BWN_PHY_SETMASK(mac, BWN_PHY_AFE_DAC_CTL, 0xf000, ctl);
13939 }
13940 
13941 static void
13942 bwn_phy_lp_set_txgain_pa(struct bwn_mac *mac, uint16_t gain)
13943 {
13944 
13945 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfb), 0xe03f, gain << 6);
13946 	BWN_PHY_SETMASK(mac, BWN_PHY_OFDM(0xfd), 0x80ff, gain << 8);
13947 }
13948 
13949 static void
13950 bwn_phy_lp_set_txgain_override(struct bwn_mac *mac)
13951 {
13952 
13953 	if (mac->mac_phy.rev < 2)
13954 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x100);
13955 	else {
13956 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x80);
13957 		BWN_PHY_SET(mac, BWN_PHY_RF_OVERRIDE_2, 0x4000);
13958 	}
13959 	BWN_PHY_SET(mac, BWN_PHY_AFE_CTL_OVR, 0x40);
13960 }
13961 
13962 static uint16_t
13963 bwn_phy_lp_get_pa_gain(struct bwn_mac *mac)
13964 {
13965 
13966 	return BWN_PHY_READ(mac, BWN_PHY_OFDM(0xfb)) & 0x7f;
13967 }
13968 
13969 static uint8_t
13970 bwn_nbits(int32_t val)
13971 {
13972 	uint32_t tmp;
13973 	uint8_t nbits = 0;
13974 
13975 	for (tmp = abs(val); tmp != 0; tmp >>= 1)
13976 		nbits++;
13977 	return (nbits);
13978 }
13979 
13980 static void
13981 bwn_phy_lp_gaintbl_write_multi(struct bwn_mac *mac, int offset, int count,
13982     struct bwn_txgain_entry *table)
13983 {
13984 	int i;
13985 
13986 	for (i = offset; i < count; i++)
13987 		bwn_phy_lp_gaintbl_write(mac, i, table[i]);
13988 }
13989 
13990 static void
13991 bwn_phy_lp_gaintbl_write(struct bwn_mac *mac, int offset,
13992     struct bwn_txgain_entry data)
13993 {
13994 
13995 	if (mac->mac_phy.rev >= 2)
13996 		bwn_phy_lp_gaintbl_write_r2(mac, offset, data);
13997 	else
13998 		bwn_phy_lp_gaintbl_write_r01(mac, offset, data);
13999 }
14000 
14001 static void
14002 bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
14003     struct bwn_txgain_entry te)
14004 {
14005 	struct bwn_softc *sc = mac->mac_sc;
14006 	struct ieee80211com *ic = &sc->sc_ic;
14007 	uint32_t tmp;
14008 
14009 	KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
14010 
14011 	tmp = (te.te_pad << 16) | (te.te_pga << 8) | te.te_gm;
14012 	if (mac->mac_phy.rev >= 3) {
14013 		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14014 		    (0x10 << 24) : (0x70 << 24));
14015 	} else {
14016 		tmp |= ((IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) ?
14017 		    (0x14 << 24) : (0x7f << 24));
14018 	}
14019 	bwn_tab_write(mac, BWN_TAB_4(7, 0xc0 + offset), tmp);
14020 	bwn_tab_write(mac, BWN_TAB_4(7, 0x140 + offset),
14021 	    te.te_bbmult << 20 | te.te_dac << 28);
14022 }
14023 
14024 static void
14025 bwn_phy_lp_gaintbl_write_r01(struct bwn_mac *mac, int offset,
14026     struct bwn_txgain_entry te)
14027 {
14028 
14029 	KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
14030 
14031 	bwn_tab_write(mac, BWN_TAB_4(10, 0xc0 + offset),
14032 	    (te.te_pad << 11) | (te.te_pga << 7) | (te.te_gm  << 4) |
14033 	    te.te_dac);
14034 	bwn_tab_write(mac, BWN_TAB_4(10, 0x140 + offset), te.te_bbmult << 20);
14035 }
14036 
14037 static void
14038 bwn_sysctl_node(struct bwn_softc *sc)
14039 {
14040 	device_t dev = sc->sc_dev;
14041 	struct bwn_mac *mac;
14042 	struct bwn_stats *stats;
14043 
14044 	/* XXX assume that count of MAC is only 1. */
14045 
14046 	if ((mac = sc->sc_curmac) == NULL)
14047 		return;
14048 	stats = &mac->mac_stats;
14049 
14050 	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14051 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14052 	    "linknoise", CTLFLAG_RW, &stats->rts, 0, "Noise level");
14053 	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14054 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14055 	    "rts", CTLFLAG_RW, &stats->rts, 0, "RTS");
14056 	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
14057 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14058 	    "rtsfail", CTLFLAG_RW, &stats->rtsfail, 0, "RTS failed to send");
14059 
14060 #ifdef BWN_DEBUG
14061 	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
14062 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
14063 	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "Debug flags");
14064 #endif
14065 }
14066 
14067 static device_method_t bwn_methods[] = {
14068 	/* Device interface */
14069 	DEVMETHOD(device_probe,		bwn_probe),
14070 	DEVMETHOD(device_attach,	bwn_attach),
14071 	DEVMETHOD(device_detach,	bwn_detach),
14072 	DEVMETHOD(device_suspend,	bwn_suspend),
14073 	DEVMETHOD(device_resume,	bwn_resume),
14074 	DEVMETHOD_END
14075 };
14076 static driver_t bwn_driver = {
14077 	"bwn",
14078 	bwn_methods,
14079 	sizeof(struct bwn_softc)
14080 };
14081 static devclass_t bwn_devclass;
14082 DRIVER_MODULE(bwn, siba_bwn, bwn_driver, bwn_devclass, 0, 0);
14083 MODULE_DEPEND(bwn, siba_bwn, 1, 1, 1);
14084 MODULE_DEPEND(bwn, wlan, 1, 1, 1);		/* 802.11 media layer */
14085 MODULE_DEPEND(bwn, firmware, 1, 1, 1);		/* firmware support */
14086 MODULE_DEPEND(bwn, wlan_amrr, 1, 1, 1);
14087