xref: /netbsd-src/sys/dev/ic/bwi.c (revision 181254a7b1bdde6873432bffef2d2decc4b5c22f)
1 /*	$NetBSD: bwi.c,v 1.37 2020/01/29 14:14:55 thorpej Exp $	*/
2 /*	$OpenBSD: bwi.c,v 1.74 2008/02/25 21:13:30 mglocker Exp $	*/
3 
4 /*
5  * Copyright (c) 2007 The DragonFly Project.  All rights reserved.
6  *
7  * This code is derived from software contributed to The DragonFly Project
8  * by Sepherosa Ziehau <sepherosa@gmail.com>
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in
18  *    the documentation and/or other materials provided with the
19  *    distribution.
20  * 3. Neither the name of The DragonFly Project nor the names of its
21  *    contributors may be used to endorse or promote products derived
22  *    from this software without specific, prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
28  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
32  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
34  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  * $DragonFly: src/sys/dev/netif/bwi/bwimac.c,v 1.1 2007/09/08 06:15:54 sephe Exp $
38  */
39 
40 /*
41  * Broadcom AirForce BCM43xx IEEE 802.11b/g wireless network driver
42  * Generic back end
43  */
44 
45 /* [TRC: XXX Names beginning with `bwi_ieee80211_*' are those that I
46    think should be in NetBSD's generic 802.11 code, not in this
47    driver.] */
48 
49 
50 #include <sys/cdefs.h>
51 __KERNEL_RCSID(0, "$NetBSD: bwi.c,v 1.37 2020/01/29 14:14:55 thorpej Exp $");
52 
53 #include <sys/param.h>
54 #include <sys/callout.h>
55 #include <sys/device.h>
56 #include <sys/kernel.h>
57 #include <sys/malloc.h>
58 #include <sys/mbuf.h>
59 #include <sys/socket.h>
60 #include <sys/sockio.h>
61 #include <sys/sysctl.h>
62 #include <sys/systm.h>
63 #include <sys/bus.h>
64 #include <sys/intr.h>
65 
66 #include <machine/endian.h>
67 
68 #include <dev/firmload.h>
69 
70 #include <net/if.h>
71 #include <net/if_dl.h>
72 #include <net/if_ether.h>
73 #include <net/if_media.h>
74 
75 #include <net/bpf.h>
76 
77 #include <net80211/ieee80211_var.h>
78 /* [TRC: XXX amrr] */
79 #include <net80211/ieee80211_amrr.h>
80 #include <net80211/ieee80211_radiotap.h>
81 
82 #include <dev/ic/bwireg.h>
83 #include <dev/ic/bwivar.h>
84 
85 #ifdef BWI_DEBUG
86 int bwi_debug = 0;
87 
88 #define DPRINTF(sc, dbg, fmt, ...)					\
89 do {									\
90 	if ((sc)->sc_debug & (dbg))					\
91 		aprint_debug_dev((sc)->sc_dev, fmt, ##__VA_ARGS__);	\
92 } while (0)
93 
94 #else	/* !BWI_DEBUG */
95 
96 #define DPRINTF(sc, dbg, fmt, ...)	((void)0)
97 
98 #endif	/* BWI_DEBUG */
99 
100 /* XXX temporary porting goop */
101 #include <dev/pci/pcireg.h>
102 #include <dev/pci/pcivar.h>
103 #include <dev/pci/pcidevs.h>
104 
105 /* XXX does not belong here */
106 #define IEEE80211_OFDM_PLCP_RATE_MASK	0x0000000f
107 #define IEEE80211_OFDM_PLCP_LEN_MASK	0x0001ffe0
108 
109 /*
110  * Contention window (slots).  [TRC: dfly/net80211/80211.h]
111  */
112 #define IEEE80211_CW_MAX	1023	/* aCWmax */
113 #define IEEE80211_CW_MIN_0	31	/* DS/CCK aCWmin, ERP aCWmin(0) */
114 #define IEEE80211_CW_MIN_1	15	/* OFDM aCWmin, ERP aCWmin(1) */
115 
116 /*
117  * Slot time (microseconds).  [TRC: dfly/net80211/80211.h]
118  */
119 #define IEEE80211_DUR_SLOT      20      /* DS/CCK slottime, ERP long slottime */
120 #define IEEE80211_DUR_SHSLOT    9       /* ERP short slottime */
121 #define IEEE80211_DUR_OFDM_SLOT 9       /* OFDM slottime */
122 
123 /* XXX end porting goop */
124 
125 /* MAC */
126 struct bwi_retry_lim {
127 	uint16_t	shretry;
128 	uint16_t	shretry_fb;
129 	uint16_t	lgretry;
130 	uint16_t	lgretry_fb;
131 };
132 
133 struct bwi_clock_freq {
134 	uint		clkfreq_min;
135 	uint		clkfreq_max;
136 };
137 
138 /* XXX does not belong here */
139 struct ieee80211_ds_plcp_hdr {
140 	uint8_t		i_signal;
141 	uint8_t		i_service;
142 	uint16_t	i_length;
143 	uint16_t	i_crc;
144 } __packed;
145 
146 static void	 bwi_sysctlattach(struct bwi_softc *);
147 
148 /* MAC */
149 static void	 bwi_tmplt_write_4(struct bwi_mac *, uint32_t, uint32_t);
150 static void	 bwi_hostflags_write(struct bwi_mac *, uint64_t);
151 static uint64_t	 bwi_hostflags_read(struct bwi_mac *);
152 static uint16_t	 bwi_memobj_read_2(struct bwi_mac *, uint16_t, uint16_t);
153 static uint32_t	 bwi_memobj_read_4(struct bwi_mac *, uint16_t, uint16_t);
154 static void	 bwi_memobj_write_2(struct bwi_mac *, uint16_t, uint16_t,
155 		     uint16_t);
156 static void	 bwi_memobj_write_4(struct bwi_mac *, uint16_t, uint16_t,
157 		     uint32_t);
158 static int	 bwi_mac_lateattach(struct bwi_mac *);
159 static int	 bwi_mac_init(struct bwi_mac *);
160 static void	 bwi_mac_reset(struct bwi_mac *, int);
161 static void	 bwi_mac_set_tpctl_11bg(struct bwi_mac *,
162 		     const struct bwi_tpctl *);
163 static int	 bwi_mac_test(struct bwi_mac *);
164 static void	 bwi_mac_setup_tpctl(struct bwi_mac *);
165 static void	 bwi_mac_dummy_xmit(struct bwi_mac *);
166 static void	 bwi_mac_init_tpctl_11bg(struct bwi_mac *);
167 static void	 bwi_mac_detach(struct bwi_mac *);
168 static int	 bwi_mac_fw_alloc(struct bwi_mac *);
169 static void	 bwi_mac_fw_free(struct bwi_mac *);
170 static int	 bwi_mac_fw_image_alloc(struct bwi_mac *, const char *,
171     		     int idx, struct bwi_fw_image *, uint8_t);
172 static void	 bwi_mac_fw_image_free(struct bwi_mac *, struct bwi_fw_image *);
173 static int	 bwi_mac_fw_load(struct bwi_mac *);
174 static int	 bwi_mac_gpio_init(struct bwi_mac *);
175 static int	 bwi_mac_gpio_fini(struct bwi_mac *);
176 static int	 bwi_mac_fw_load_iv(struct bwi_mac *,
177 		     const struct bwi_fw_image *);
178 static int	 bwi_mac_fw_init(struct bwi_mac *);
179 static void	 bwi_mac_opmode_init(struct bwi_mac *);
180 static void	 bwi_mac_hostflags_init(struct bwi_mac *);
181 static void	 bwi_mac_bss_param_init(struct bwi_mac *);
182 static void	 bwi_mac_set_retry_lim(struct bwi_mac *,
183 		     const struct bwi_retry_lim *);
184 static void	 bwi_mac_set_ackrates(struct bwi_mac *,
185 		     const struct ieee80211_rateset *);
186 static int	 bwi_mac_start(struct bwi_mac *);
187 static int	 bwi_mac_stop(struct bwi_mac *);
188 static int	 bwi_mac_config_ps(struct bwi_mac *);
189 static void	 bwi_mac_reset_hwkeys(struct bwi_mac *);
190 static void	 bwi_mac_shutdown(struct bwi_mac *);
191 static int	 bwi_mac_get_property(struct bwi_mac *);
192 static void	 bwi_mac_updateslot(struct bwi_mac *, int);
193 static int	 bwi_mac_attach(struct bwi_softc *, int, uint8_t);
194 static void	 bwi_mac_balance_atten(int *, int *);
195 static void	 bwi_mac_adjust_tpctl(struct bwi_mac *, int, int);
196 static void	 bwi_mac_calibrate_txpower(struct bwi_mac *,
197 		     enum bwi_txpwrcb_type);
198 static void	 bwi_mac_lock(struct bwi_mac *);
199 static void	 bwi_mac_unlock(struct bwi_mac *);
200 static void	 bwi_mac_set_promisc(struct bwi_mac *, int);
201 
202 /* PHY */
203 static void	 bwi_phy_write(struct bwi_mac *, uint16_t, uint16_t);
204 static uint16_t	 bwi_phy_read(struct bwi_mac *, uint16_t);
205 static int	 bwi_phy_attach(struct bwi_mac *);
206 static void	 bwi_phy_set_bbp_atten(struct bwi_mac *, uint16_t);
207 static int	 bwi_phy_calibrate(struct bwi_mac *);
208 static void	 bwi_tbl_write_2(struct bwi_mac *mac, uint16_t, uint16_t);
209 static void	 bwi_tbl_write_4(struct bwi_mac *mac, uint16_t, uint32_t);
210 static void	 bwi_nrssi_write(struct bwi_mac *, uint16_t, int16_t);
211 static int16_t	 bwi_nrssi_read(struct bwi_mac *, uint16_t);
212 static void	 bwi_phy_init_11a(struct bwi_mac *);
213 static void	 bwi_phy_init_11g(struct bwi_mac *);
214 static void	 bwi_phy_init_11b_rev2(struct bwi_mac *);
215 static void	 bwi_phy_init_11b_rev4(struct bwi_mac *);
216 static void	 bwi_phy_init_11b_rev5(struct bwi_mac *);
217 static void	 bwi_phy_init_11b_rev6(struct bwi_mac *);
218 static void	 bwi_phy_config_11g(struct bwi_mac *);
219 static void	 bwi_phy_config_agc(struct bwi_mac *);
220 static void	 bwi_set_gains(struct bwi_mac *, const struct bwi_gains *);
221 static void	 bwi_phy_clear_state(struct bwi_phy *);
222 
223 /* RF */
224 static int16_t	 bwi_nrssi_11g(struct bwi_mac *);
225 static struct bwi_rf_lo
226 		*bwi_get_rf_lo(struct bwi_mac *, uint16_t, uint16_t);
227 static int	 bwi_rf_lo_isused(struct bwi_mac *, const struct bwi_rf_lo *);
228 static void	 bwi_rf_write(struct bwi_mac *, uint16_t, uint16_t);
229 static uint16_t	 bwi_rf_read(struct bwi_mac *, uint16_t);
230 static int	 bwi_rf_attach(struct bwi_mac *);
231 static void	 bwi_rf_set_chan(struct bwi_mac *, uint, int);
232 static void	 bwi_rf_get_gains(struct bwi_mac *);
233 static void	 bwi_rf_init(struct bwi_mac *);
234 static void	 bwi_rf_off_11a(struct bwi_mac *);
235 static void	 bwi_rf_off_11bg(struct bwi_mac *);
236 static void	 bwi_rf_off_11g_rev5(struct bwi_mac *);
237 static void	 bwi_rf_workaround(struct bwi_mac *, uint);
238 static struct bwi_rf_lo
239 		*bwi_rf_lo_find(struct bwi_mac *, const struct bwi_tpctl *);
240 static void	 bwi_rf_lo_adjust(struct bwi_mac *, const struct bwi_tpctl *);
241 static void	 bwi_rf_lo_write(struct bwi_mac *, const struct bwi_rf_lo *);
242 static int	 bwi_rf_gain_max_reached(struct bwi_mac *, int);
243 static uint16_t	 bwi_bitswap4(uint16_t);
244 static uint16_t	 bwi_phy812_value(struct bwi_mac *, uint16_t);
245 static void	 bwi_rf_init_bcm2050(struct bwi_mac *);
246 static uint16_t	 bwi_rf_calibval(struct bwi_mac *);
247 static int32_t	 _bwi_adjust_devide(int32_t, int32_t);
248 static int	 bwi_rf_calc_txpower(int8_t *, uint8_t, const int16_t[]);
249 static int	 bwi_rf_map_txpower(struct bwi_mac *);
250 static void	 bwi_rf_lo_update_11g(struct bwi_mac *);
251 static uint32_t	 bwi_rf_lo_devi_measure(struct bwi_mac *, uint16_t);
252 static uint16_t	 bwi_rf_get_tp_ctrl2(struct bwi_mac *);
253 static uint8_t	 _bwi_rf_lo_update_11g(struct bwi_mac *, uint16_t);
254 static void	 bwi_rf_lo_measure_11g(struct bwi_mac *,
255 		     const struct bwi_rf_lo *, struct bwi_rf_lo *, uint8_t);
256 static void	 bwi_rf_calc_nrssi_slope_11b(struct bwi_mac *);
257 static void	 bwi_rf_set_nrssi_ofs_11g(struct bwi_mac *);
258 static void	 bwi_rf_calc_nrssi_slope_11g(struct bwi_mac *);
259 static void	 bwi_rf_init_sw_nrssi_table(struct bwi_mac *);
260 static void	 bwi_rf_init_hw_nrssi_table(struct bwi_mac *, uint16_t);
261 static void	 bwi_rf_set_nrssi_thr_11b(struct bwi_mac *);
262 static int32_t	 _nrssi_threshold(const struct bwi_rf *, int32_t);
263 static void	 bwi_rf_set_nrssi_thr_11g(struct bwi_mac *);
264 static void	 bwi_rf_clear_tssi(struct bwi_mac *);
265 static void	 bwi_rf_clear_state(struct bwi_rf *);
266 static void	 bwi_rf_on_11a(struct bwi_mac *);
267 static void	 bwi_rf_on_11bg(struct bwi_mac *);
268 static void	 bwi_rf_set_ant_mode(struct bwi_mac *, int);
269 static int	 bwi_rf_get_latest_tssi(struct bwi_mac *, int8_t[], uint16_t);
270 static int	 bwi_rf_tssi2dbm(struct bwi_mac *, int8_t, int8_t *);
271 static int	 bwi_rf_calc_rssi_bcm2050(struct bwi_mac *,
272 		     const struct bwi_rxbuf_hdr *);
273 static int	 bwi_rf_calc_rssi_bcm2053(struct bwi_mac *,
274 		     const struct bwi_rxbuf_hdr *);
275 static int	 bwi_rf_calc_rssi_bcm2060(struct bwi_mac *,
276 		     const struct bwi_rxbuf_hdr *);
277 static uint16_t	 bwi_rf_lo_measure_11b(struct bwi_mac *);
278 static void	 bwi_rf_lo_update_11b(struct bwi_mac *);
279 
280 /* INTERFACE */
281 static uint16_t	 bwi_read_sprom(struct bwi_softc *, uint16_t);
282 static void	 bwi_setup_desc32(struct bwi_softc *, struct bwi_desc32 *, int,
283 		     int, bus_addr_t, int, int);
284 static void	 bwi_power_on(struct bwi_softc *, int);
285 static int	 bwi_power_off(struct bwi_softc *, int);
286 static int	 bwi_regwin_switch(struct bwi_softc *, struct bwi_regwin *,
287 		     struct bwi_regwin **);
288 static int	 bwi_regwin_select(struct bwi_softc *, int);
289 static void	 bwi_regwin_info(struct bwi_softc *, uint16_t *, uint8_t *);
290 static void	 bwi_led_attach(struct bwi_softc *);
291 static void	 bwi_led_newstate(struct bwi_softc *, enum ieee80211_state);
292 static uint16_t	 bwi_led_onoff(const struct bwi_led *, uint16_t, int);
293 static void	 bwi_led_event(struct bwi_softc *, int);
294 static void	 bwi_led_blink_start(struct bwi_softc *, int, int);
295 static void	 bwi_led_blink_next(void *);
296 static void	 bwi_led_blink_end(void *);
297 static int	 bwi_bbp_attach(struct bwi_softc *);
298 static int	 bwi_bus_init(struct bwi_softc *, struct bwi_mac *);
299 static void	 bwi_get_card_flags(struct bwi_softc *);
300 static void	 bwi_get_eaddr(struct bwi_softc *, uint16_t, uint8_t *);
301 static void	 bwi_get_clock_freq(struct bwi_softc *,
302 		     struct bwi_clock_freq *);
303 static int	 bwi_set_clock_mode(struct bwi_softc *, enum bwi_clock_mode);
304 static int	 bwi_set_clock_delay(struct bwi_softc *);
305 static int	 bwi_init(struct ifnet *);
306 static void	 bwi_init_statechg(struct bwi_softc *, int);
307 static int	 bwi_ioctl(struct ifnet *, u_long, void *);
308 static void	 bwi_start(struct ifnet *);
309 static void	 bwi_watchdog(struct ifnet *);
310 static void	 bwi_stop(struct ifnet *, int);
311 static void	 bwi_newstate_begin(struct bwi_softc *, enum ieee80211_state);
312 static int	 bwi_newstate(struct ieee80211com *, enum ieee80211_state, int);
313 static int	 bwi_media_change(struct ifnet *);
314 /* [TRC: XXX amrr] */
315 static void	 bwi_iter_func(void *, struct ieee80211_node *);
316 static void	 bwi_amrr_timeout(void *);
317 static void	 bwi_newassoc(struct ieee80211_node *, int);
318 static struct ieee80211_node *
319 		 bwi_node_alloc(struct ieee80211_node_table *);
320 static int	 bwi_dma_alloc(struct bwi_softc *);
321 static void	 bwi_dma_free(struct bwi_softc *);
322 static void	 bwi_ring_data_free(struct bwi_ring_data *, struct bwi_softc *);
323 static int	 bwi_dma_ring_alloc(struct bwi_softc *,
324 		     struct bwi_ring_data *, bus_size_t, uint32_t);
325 static int	 bwi_dma_txstats_alloc(struct bwi_softc *, uint32_t,
326 		     bus_size_t);
327 static void	 bwi_dma_txstats_free(struct bwi_softc *);
328 static int	 bwi_dma_mbuf_create(struct bwi_softc *);
329 static void	 bwi_dma_mbuf_destroy(struct bwi_softc *, int, int);
330 static void	 bwi_enable_intrs(struct bwi_softc *, uint32_t);
331 static void	 bwi_disable_intrs(struct bwi_softc *, uint32_t);
332 static int	 bwi_init_tx_ring32(struct bwi_softc *, int);
333 static void	 bwi_init_rxdesc_ring32(struct bwi_softc *, uint32_t,
334 		     bus_addr_t, int, int);
335 static int	 bwi_init_rx_ring32(struct bwi_softc *);
336 static int	 bwi_init_txstats32(struct bwi_softc *);
337 static void	 bwi_setup_rx_desc32(struct bwi_softc *, int, bus_addr_t, int);
338 static void	 bwi_setup_tx_desc32(struct bwi_softc *, struct bwi_ring_data *,
339 		     int, bus_addr_t, int);
340 static int	 bwi_init_tx_ring64(struct bwi_softc *, int);
341 static int	 bwi_init_rx_ring64(struct bwi_softc *);
342 static int	 bwi_init_txstats64(struct bwi_softc *);
343 static void	 bwi_setup_rx_desc64(struct bwi_softc *, int, bus_addr_t, int);
344 static void	 bwi_setup_tx_desc64(struct bwi_softc *, struct bwi_ring_data *,
345 		     int, bus_addr_t, int);
346 static int	 bwi_newbuf(struct bwi_softc *, int, int);
347 static void	 bwi_set_addr_filter(struct bwi_softc *, uint16_t,
348 		     const uint8_t *);
349 static int	 bwi_set_chan(struct bwi_softc *, struct ieee80211_channel *);
350 static void	 bwi_next_scan(void *);
351 static int	 bwi_rxeof(struct bwi_softc *, int);
352 static int	 bwi_rxeof32(struct bwi_softc *);
353 static int	 bwi_rxeof64(struct bwi_softc *);
354 static void	 bwi_reset_rx_ring32(struct bwi_softc *, uint32_t);
355 static void	 bwi_free_txstats32(struct bwi_softc *);
356 static void	 bwi_free_rx_ring32(struct bwi_softc *);
357 static void	 bwi_free_tx_ring32(struct bwi_softc *, int);
358 static void	 bwi_free_txstats64(struct bwi_softc *);
359 static void	 bwi_free_rx_ring64(struct bwi_softc *);
360 static void	 bwi_free_tx_ring64(struct bwi_softc *, int);
361 static uint8_t	 bwi_ieee80211_rate2plcp(uint8_t rate, enum ieee80211_phymode);
362 static uint8_t	 bwi_ieee80211_plcp2rate(uint8_t rate, enum ieee80211_phymode);
363 static enum bwi_ieee80211_modtype
364 		 bwi_ieee80211_rate2modtype(uint8_t rate);
365 static uint8_t	 bwi_ofdm_plcp2rate(const void *);
366 static uint8_t	 bwi_ds_plcp2rate(const struct ieee80211_ds_plcp_hdr *);
367 static void	 bwi_ofdm_plcp_header(uint32_t *, int, uint8_t);
368 static void	 bwi_ds_plcp_header(struct ieee80211_ds_plcp_hdr *, int,
369 		     uint8_t);
370 static void	 bwi_plcp_header(void *, int, uint8_t);
371 static int	 bwi_encap(struct bwi_softc *, int, struct mbuf *,
372 		     struct ieee80211_node **, int);
373 static void	 bwi_start_tx32(struct bwi_softc *, uint32_t, int);
374 static void	 bwi_start_tx64(struct bwi_softc *, uint32_t, int);
375 static void	 bwi_txeof_status32(struct bwi_softc *);
376 static void	 bwi_txeof_status64(struct bwi_softc *);
377 static void	 _bwi_txeof(struct bwi_softc *, uint16_t);
378 static void	 bwi_txeof_status(struct bwi_softc *, int);
379 static void	 bwi_txeof(struct bwi_softc *);
380 static int	 bwi_bbp_power_on(struct bwi_softc *, enum bwi_clock_mode);
381 static void	 bwi_bbp_power_off(struct bwi_softc *);
382 static int	 bwi_get_pwron_delay(struct bwi_softc *sc);
383 static int	 bwi_bus_attach(struct bwi_softc *);
384 static const char
385 		*bwi_regwin_name(const struct bwi_regwin *);
386 static int	 bwi_regwin_is_enabled(struct bwi_softc *, struct bwi_regwin *);
387 static uint32_t	 bwi_regwin_disable_bits(struct bwi_softc *);
388 static void	 bwi_regwin_enable(struct bwi_softc *, struct bwi_regwin *,
389 		     uint32_t);
390 static void	 bwi_regwin_disable(struct bwi_softc *, struct bwi_regwin *,
391 		     uint32_t);
392 static void	 bwi_set_bssid(struct bwi_softc *, const uint8_t *);
393 static void	 bwi_updateslot(struct ifnet *);
394 static void	 bwi_calibrate(void *);
395 static int	 bwi_calc_rssi(struct bwi_softc *,
396 		     const struct bwi_rxbuf_hdr *);
397 static uint8_t	 bwi_ieee80211_ack_rate(struct ieee80211_node *, uint8_t);
398 static uint16_t	 bwi_ieee80211_txtime(struct ieee80211com *,
399 		     struct ieee80211_node *, uint, uint8_t, uint32_t);
400 
401 /* MAC */
402 static const uint8_t bwi_sup_macrev[] = { 2, 4, 5, 6, 7, 9, 10, 12 };
403 
404 /* PHY */
405 #define SUP_BPHY(num)	{ .rev = num, .init = bwi_phy_init_11b_rev##num }
406 
407 static const struct {
408 	uint8_t	rev;
409 	void	(*init)(struct bwi_mac *);
410 } bwi_sup_bphy[] = {
411 	SUP_BPHY(2),
412 	SUP_BPHY(4),
413 	SUP_BPHY(5),
414 	SUP_BPHY(6)
415 };
416 
417 #undef SUP_BPHY
418 
419 #define BWI_PHYTBL_WRSSI	0x1000
420 #define BWI_PHYTBL_NOISE_SCALE	0x1400
421 #define BWI_PHYTBL_NOISE	0x1800
422 #define BWI_PHYTBL_ROTOR	0x2000
423 #define BWI_PHYTBL_DELAY	0x2400
424 #define BWI_PHYTBL_RSSI		0x4000
425 #define BWI_PHYTBL_SIGMA_SQ	0x5000
426 #define BWI_PHYTBL_WRSSI_REV1	0x5400
427 #define BWI_PHYTBL_FREQ		0x5800
428 
429 static const uint16_t	bwi_phy_freq_11g_rev1[] =
430 	{ BWI_PHY_FREQ_11G_REV1 };
431 static const uint16_t	bwi_phy_noise_11g_rev1[] =
432 	{ BWI_PHY_NOISE_11G_REV1 };
433 static const uint16_t	bwi_phy_noise_11g[] =
434 	{ BWI_PHY_NOISE_11G };
435 static const uint32_t	bwi_phy_rotor_11g_rev1[] =
436 	{ BWI_PHY_ROTOR_11G_REV1 };
437 static const uint16_t	bwi_phy_noise_scale_11g_rev2[] =
438 	{ BWI_PHY_NOISE_SCALE_11G_REV2 };
439 static const uint16_t	bwi_phy_noise_scale_11g_rev7[] =
440 	{ BWI_PHY_NOISE_SCALE_11G_REV7 };
441 static const uint16_t	bwi_phy_noise_scale_11g[] =
442 	{ BWI_PHY_NOISE_SCALE_11G };
443 static const uint16_t	bwi_phy_sigma_sq_11g_rev2[] =
444 	{ BWI_PHY_SIGMA_SQ_11G_REV2 };
445 static const uint16_t	bwi_phy_sigma_sq_11g_rev7[] =
446 	{ BWI_PHY_SIGMA_SQ_11G_REV7 };
447 static const uint32_t	bwi_phy_delay_11g_rev1[] =
448 	{ BWI_PHY_DELAY_11G_REV1 };
449 
450 /* RF */
451 #define RF_LO_WRITE(mac, lo)	bwi_rf_lo_write((mac), (lo))
452 
453 #define BWI_RF_2GHZ_CHAN(chan) \
454 	(ieee80211_ieee2mhz((chan), IEEE80211_CHAN_2GHZ) - 2400)
455 
456 #define BWI_DEFAULT_IDLE_TSSI	52
457 
458 struct rf_saveregs {
459 	uint16_t	phy_01;
460 	uint16_t	phy_03;
461 	uint16_t	phy_0a;
462 	uint16_t	phy_15;
463 	uint16_t	phy_2a;
464 	uint16_t	phy_30;
465 	uint16_t	phy_35;
466 	uint16_t	phy_60;
467 	uint16_t	phy_429;
468 	uint16_t	phy_802;
469 	uint16_t	phy_811;
470 	uint16_t	phy_812;
471 	uint16_t	phy_814;
472 	uint16_t	phy_815;
473 
474 	uint16_t	rf_43;
475 	uint16_t	rf_52;
476 	uint16_t	rf_7a;
477 };
478 
479 #define SAVE_RF_REG(mac, regs, n)	(regs)->rf_##n = RF_READ((mac), 0x##n)
480 #define RESTORE_RF_REG(mac, regs, n)	RF_WRITE((mac), 0x##n, (regs)->rf_##n)
481 
482 #define SAVE_PHY_REG(mac, regs, n)	(regs)->phy_##n = PHY_READ((mac), 0x##n)
483 #define RESTORE_PHY_REG(mac, regs, n)	PHY_WRITE((mac), 0x##n, (regs)->phy_##n)
484 
485 static const int8_t	bwi_txpower_map_11b[BWI_TSSI_MAX] =
486 	{ BWI_TXPOWER_MAP_11B };
487 static const int8_t	bwi_txpower_map_11g[BWI_TSSI_MAX] =
488 	{ BWI_TXPOWER_MAP_11G };
489 
490 /* INTERFACE */
491 
492 struct bwi_myaddr_bssid {
493 	uint8_t		myaddr[IEEE80211_ADDR_LEN];
494 	uint8_t		bssid[IEEE80211_ADDR_LEN];
495 } __packed;
496 
497 /* [TRC: XXX What are these about?] */
498 
499 #define IEEE80211_DS_PLCP_SERVICE_LOCKED	0x04
500 #define IEEE80211_DS_PLCL_SERVICE_PBCC		0x08
501 #define IEEE80211_DS_PLCP_SERVICE_LENEXT5	0x20
502 #define IEEE80211_DS_PLCP_SERVICE_LENEXT6	0x40
503 #define IEEE80211_DS_PLCP_SERVICE_LENEXT7	0x80
504 
505 static const struct {
506 	uint16_t	did_min;
507 	uint16_t	did_max;
508 	uint16_t	bbp_id;
509 } bwi_bbpid_map[] = {
510 	{ 0x4301, 0x4301, 0x4301 },
511 	{ 0x4305, 0x4307, 0x4307 },
512 	{ 0x4403, 0x4403, 0x4402 },
513 	{ 0x4610, 0x4615, 0x4610 },
514 	{ 0x4710, 0x4715, 0x4710 },
515 	{ 0x4720, 0x4725, 0x4309 }
516 };
517 
518 static const struct {
519 	uint16_t	bbp_id;
520 	int		nregwin;
521 } bwi_regwin_count[] = {
522 	{ 0x4301, 5 },
523 	{ 0x4306, 6 },
524 	{ 0x4307, 5 },
525 	{ 0x4310, 8 },
526 	{ 0x4401, 3 },
527 	{ 0x4402, 3 },
528 	{ 0x4610, 9 },
529 	{ 0x4704, 9 },
530 	{ 0x4710, 9 },
531 	{ 0x5365, 7 }
532 };
533 
534 #define CLKSRC(src) 				\
535 [BWI_CLKSRC_ ## src] = {			\
536 	.freq_min = BWI_CLKSRC_ ##src## _FMIN,	\
537 	.freq_max = BWI_CLKSRC_ ##src## _FMAX	\
538 }
539 
540 static const struct {
541 	uint	freq_min;
542 	uint	freq_max;
543 } bwi_clkfreq[BWI_CLKSRC_MAX] = {
544 	CLKSRC(LP_OSC),
545 	CLKSRC(CS_OSC),
546 	CLKSRC(PCI)
547 };
548 
549 #undef CLKSRC
550 
551 #define VENDOR_LED_ACT(vendor)				\
552 {							\
553 	.vid = PCI_VENDOR_##vendor,			\
554 	.led_act = { BWI_VENDOR_LED_ACT_##vendor }	\
555 }
556 
557 static const struct {
558 	uint16_t	vid;
559 	uint8_t		led_act[BWI_LED_MAX];
560 } bwi_vendor_led_act[] = {
561 	VENDOR_LED_ACT(COMPAQ),
562 	VENDOR_LED_ACT(LINKSYS)
563 };
564 
565 static const uint8_t bwi_default_led_act[BWI_LED_MAX] =
566 	{ BWI_VENDOR_LED_ACT_DEFAULT };
567 
568 #undef VENDOR_LED_ACT
569 
570 static const struct {
571 	int	on_dur;
572 	int	off_dur;
573 } bwi_led_duration[109] = {
574 	[0]	= { 400, 100 },
575 	[2]	= { 150, 75 },
576 	[4]	= { 90, 45 },
577 	[11]	= { 66, 34 },
578 	[12]	= { 53, 26 },
579 	[18]	= { 42, 21 },
580 	[22]	= { 35, 17 },
581 	[24]	= { 32, 16 },
582 	[36]	= { 21, 10 },
583 	[48]	= { 16, 8 },
584 	[72]	= { 11, 5 },
585 	[96]	= { 9, 4 },
586 	[108]	= { 7, 3 }
587 };
588 
589 /* [TRC: XXX Should this be zeroed?] */
590 
591 static const uint8_t bwi_zero_addr[IEEE80211_ADDR_LEN];
592 
593 /* [TRC: Derived from DragonFly's src/sys/netproto/802_11/_ieee80211.h */
594 
595 enum bwi_ieee80211_modtype {
596 	IEEE80211_MODTYPE_DS	= 0,	/* DS/CCK modulation */
597 	IEEE80211_MODTYPE_PBCC	= 1,	/* PBCC modulation */
598 	IEEE80211_MODTYPE_OFDM	= 2	/* OFDM modulation */
599 };
600 #define IEEE80211_MODTYPE_CCK   IEEE80211_MODTYPE_DS
601 
602 /*
603  * Setup sysctl(3) MIB, hw.bwi.* and hw.bwiN.*
604  */
605 
606 #ifdef BWI_DEBUG
607 SYSCTL_SETUP(sysctl_bwi, "sysctl bwi(4) subtree setup")
608 {
609 	int rc;
610 	const struct sysctlnode *rnode;
611 	const struct sysctlnode *cnode;
612 
613 	if ((rc = sysctl_createv(clog, 0, NULL, &rnode,
614 	    CTLFLAG_PERMANENT, CTLTYPE_NODE, "bwi",
615 	    SYSCTL_DESCR("bwi global controls"),
616 	    NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0)
617 		goto err;
618 
619 	if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
620 	    CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
621 	    "debug", SYSCTL_DESCR("default debug flags"),
622 	    NULL, 0, &bwi_debug, 0, CTL_CREATE, CTL_EOL)) != 0)
623 		goto err;
624 
625 	return;
626 
627 err:
628 	aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc);
629 }
630 #endif	/* BWI_DEBUG */
631 
632 static void
633 bwi_sysctlattach(struct bwi_softc *sc)
634 {
635 	int rc;
636 	const struct sysctlnode *rnode;
637 	const struct sysctlnode *cnode;
638 
639 	struct sysctllog **clog = &sc->sc_sysctllog;
640 
641 	if ((rc = sysctl_createv(clog, 0, NULL, &rnode,
642 	    CTLFLAG_PERMANENT, CTLTYPE_NODE, device_xname(sc->sc_dev),
643 	    SYSCTL_DESCR("bwi controls and statistics"),
644 	    NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0)
645 		goto err;
646 
647 	if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
648 	    CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
649 	    "fw_version", SYSCTL_DESCR("firmware version"),
650 	    NULL, 0, &sc->sc_fw_version, 0, CTL_CREATE, CTL_EOL)) != 0)
651 		goto err;
652 
653 	if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
654 	    CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
655 	    "dwell_time", SYSCTL_DESCR("channel dwell time during scan (msec)"),
656 	    NULL, 0, &sc->sc_dwell_time, 0, CTL_CREATE, CTL_EOL)) != 0)
657 		goto err;
658 
659 	if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
660 	    CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
661 	    "led_idle", SYSCTL_DESCR("# ticks before LED enters idle state"),
662 	    NULL, 0, &sc->sc_led_idle, 0, CTL_CREATE, CTL_EOL)) != 0)
663 		goto err;
664 
665 	if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
666 	    CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
667 	    "led_blink", SYSCTL_DESCR("allow LED to blink"),
668 	    NULL, 0, &sc->sc_led_blink, 0, CTL_CREATE, CTL_EOL)) != 0)
669 		goto err;
670 
671 	if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
672 	    CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
673 	    "txpwr_calib", SYSCTL_DESCR("enable software TX power calibration"),
674 	    NULL, 0, &sc->sc_txpwr_calib, 0, CTL_CREATE, CTL_EOL)) != 0)
675 		goto err;
676 
677 #ifdef BWI_DEBUG
678 	if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
679 	    CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
680 	    "debug", SYSCTL_DESCR("debug flags"),
681 	    NULL, 0, &sc->sc_debug, 0, CTL_CREATE, CTL_EOL)) != 0)
682 		goto err;
683 #endif
684 
685 	return;
686 
687 err:
688 	aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc);
689 }
690 
691 /* CODE */
692 
693 int
694 bwi_intr(void *arg)
695 {
696 	struct bwi_softc *sc = arg;
697 	struct ifnet *ifp = &sc->sc_if;
698 
699 	if (!device_is_active(sc->sc_dev) ||
700 	    (ifp->if_flags & IFF_RUNNING) == 0)
701 		return (0);
702 
703 	/* Disable all interrupts */
704 	bwi_disable_intrs(sc, BWI_ALL_INTRS);
705 
706 	softint_schedule(sc->sc_soft_ih);
707 	return (1);
708 }
709 
710 static void
711 bwi_softintr(void *arg)
712 {
713 	struct bwi_softc *sc = arg;
714 	struct bwi_mac *mac;
715 	struct ifnet *ifp = &sc->sc_if;
716 	uint32_t intr_status;
717 	uint32_t txrx_intr_status[BWI_TXRX_NRING];
718 	int i, s, txrx_error, tx = 0, rx_data = -1;
719 
720 	if (!device_is_active(sc->sc_dev) ||
721 	    (ifp->if_flags & IFF_RUNNING) == 0)
722 		return;
723 
724 	for (;;) {
725 		/*
726 		 * Get interrupt status
727 		 */
728 		intr_status = CSR_READ_4(sc, BWI_MAC_INTR_STATUS);
729 		if (intr_status == 0xffffffff)	/* Not for us */
730 			goto out;
731 
732 		intr_status &= CSR_READ_4(sc, BWI_MAC_INTR_MASK);
733 		if (intr_status == 0)		/* Nothing is interesting */
734 			goto out;
735 
736 		DPRINTF(sc, BWI_DBG_INTR, "intr status 0x%08x\n", intr_status);
737 
738 		KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
739 		mac = (struct bwi_mac *)sc->sc_cur_regwin;
740 
741 		txrx_error = 0;
742 
743 		for (i = 0; i < BWI_TXRX_NRING; ++i) {
744 			uint32_t mask;
745 
746 			if (BWI_TXRX_IS_RX(i))
747 				mask = BWI_TXRX_RX_INTRS;
748 			else
749 				mask = BWI_TXRX_TX_INTRS;
750 
751 			txrx_intr_status[i] =
752 			    CSR_READ_4(sc, BWI_TXRX_INTR_STATUS(i)) & mask;
753 
754 			if (txrx_intr_status[i] & BWI_TXRX_INTR_ERROR) {
755 				aprint_error_dev(sc->sc_dev,
756 				    "intr fatal TX/RX (%d) error 0x%08x\n",
757 				    i, txrx_intr_status[i]);
758 				txrx_error = 1;
759 			}
760 		}
761 
762 		/*
763 		 * Acknowledge interrupt
764 		 */
765 		CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, intr_status);
766 
767 		for (i = 0; i < BWI_TXRX_NRING; ++i)
768 			CSR_WRITE_4(sc, BWI_TXRX_INTR_STATUS(i),
769 			    txrx_intr_status[i]);
770 
771 		if (intr_status & BWI_INTR_PHY_TXERR) {
772 			if (mac->mac_flags & BWI_MAC_F_PHYE_RESET) {
773 				aprint_error_dev(sc->sc_dev,
774 				    "intr PHY TX error\n");
775 				/* XXX to netisr0? */
776 				s = splnet();
777 				bwi_init_statechg(sc, 0);
778 				splx(s);
779 				goto out;
780 			}
781 		}
782 
783 		if (txrx_error) {
784 			/* TODO: reset device */
785 		}
786 
787 		if (intr_status & BWI_INTR_TBTT)
788 			bwi_mac_config_ps(mac);
789 
790 		if (intr_status & BWI_INTR_EO_ATIM)
791 			aprint_normal_dev(sc->sc_dev, "EO_ATIM\n");
792 
793 		if (intr_status & BWI_INTR_PMQ) {
794 			for (;;) {
795 				if ((CSR_READ_4(sc, BWI_MAC_PS_STATUS) & 0x8)
796 				    == 0)
797 					break;
798 			}
799 			CSR_WRITE_2(sc, BWI_MAC_PS_STATUS, 0x2);
800 		}
801 
802 		if (intr_status & BWI_INTR_NOISE)
803 			aprint_normal_dev(sc->sc_dev, "intr noise\n");
804 
805 		if (txrx_intr_status[0] & BWI_TXRX_INTR_RX)
806 			rx_data = (sc->sc_rxeof)(sc);
807 
808 		if (txrx_intr_status[3] & BWI_TXRX_INTR_RX) {
809 			(sc->sc_txeof_status)(sc);
810 			tx = 1;
811 		}
812 
813 		if (intr_status & BWI_INTR_TX_DONE) {
814 			bwi_txeof(sc);
815 			tx = 1;
816 		}
817 
818 		if (sc->sc_blink_led != NULL && sc->sc_led_blink) {
819 			int evt = BWI_LED_EVENT_NONE;
820 
821 			if (tx && rx_data > 0) {
822 				if (sc->sc_rx_rate > sc->sc_tx_rate)
823 					evt = BWI_LED_EVENT_RX;
824 				else
825 					evt = BWI_LED_EVENT_TX;
826 			} else if (tx) {
827 				evt = BWI_LED_EVENT_TX;
828 			} else if (rx_data > 0) {
829 				evt = BWI_LED_EVENT_RX;
830 			} else if (rx_data == 0) {
831 				evt = BWI_LED_EVENT_POLL;
832 			}
833 
834 			if (evt != BWI_LED_EVENT_NONE)
835 				bwi_led_event(sc, evt);
836 		}
837 	}
838 
839 out:
840 	/* Re-enable interrupts */
841 	bwi_enable_intrs(sc, BWI_INIT_INTRS);
842 }
843 
844 int
845 bwi_attach(struct bwi_softc *sc)
846 {
847 	struct ieee80211com *ic = &sc->sc_ic;
848 	struct ifnet *ifp = &sc->sc_if;
849 	struct bwi_mac *mac;
850 	struct bwi_phy *phy;
851 	int s, i, error;
852 
853 	/* [TRC: XXX Is this necessary?] */
854 	s = splnet();
855 
856 	sc->sc_soft_ih = softint_establish(SOFTINT_NET, bwi_softintr, sc);
857 	if (sc->sc_soft_ih == NULL) {
858 		error = ENXIO;
859 		goto fail;
860 	}
861 
862 	/*
863 	 * Initialize sysctl variables
864 	 */
865 	sc->sc_fw_version = BWI_FW_VERSION3;
866 	sc->sc_dwell_time = 200;
867 	sc->sc_led_idle = (2350 * hz) / 1000;
868 	sc->sc_led_blink = 1;
869 	sc->sc_txpwr_calib = 1;
870 #ifdef BWI_DEBUG
871 	sc->sc_debug = bwi_debug;
872 #endif
873 
874 	DPRINTF(sc, BWI_DBG_ATTACH, "%s\n", __func__);
875 
876 	/* [TRC: XXX amrr] */
877 	/* AMRR rate control */
878 	sc->sc_amrr.amrr_min_success_threshold = 1;
879 	sc->sc_amrr.amrr_max_success_threshold = 15;
880 	callout_init(&sc->sc_amrr_ch, 0);
881 	callout_setfunc(&sc->sc_amrr_ch, bwi_amrr_timeout, sc);
882 
883 	callout_init(&sc->sc_scan_ch, 0);
884 	callout_setfunc(&sc->sc_scan_ch, bwi_next_scan, sc);
885 	callout_init(&sc->sc_calib_ch, 0);
886 	callout_setfunc(&sc->sc_calib_ch, bwi_calibrate, sc);
887 
888 	bwi_sysctlattach(sc);
889 
890 	bwi_power_on(sc, 1);
891 
892 	error = bwi_bbp_attach(sc);
893 	if (error)
894 		goto fail;
895 
896 	error = bwi_bbp_power_on(sc, BWI_CLOCK_MODE_FAST);
897 	if (error)
898 		goto fail;
899 
900 	if (BWI_REGWIN_EXIST(&sc->sc_com_regwin)) {
901 		error = bwi_set_clock_delay(sc);
902 		if (error)
903 			goto fail;
904 
905 		error = bwi_set_clock_mode(sc, BWI_CLOCK_MODE_FAST);
906 		if (error)
907 			goto fail;
908 
909 		error = bwi_get_pwron_delay(sc);
910 		if (error)
911 			goto fail;
912 	}
913 
914 	error = bwi_bus_attach(sc);
915 	if (error)
916 		goto fail;
917 
918 	bwi_get_card_flags(sc);
919 
920 	bwi_led_attach(sc);
921 
922 	for (i = 0; i < sc->sc_nmac; ++i) {
923 		struct bwi_regwin *old;
924 
925 		mac = &sc->sc_mac[i];
926 		error = bwi_regwin_switch(sc, &mac->mac_regwin, &old);
927 		if (error)
928 			goto fail;
929 
930 		error = bwi_mac_lateattach(mac);
931 		if (error)
932 			goto fail;
933 
934 		error = bwi_regwin_switch(sc, old, NULL);
935 		if (error)
936 			goto fail;
937 	}
938 
939 	/*
940 	 * XXX First MAC is known to exist
941 	 * TODO2
942 	 */
943 	mac = &sc->sc_mac[0];
944 	phy = &mac->mac_phy;
945 
946 	bwi_bbp_power_off(sc);
947 
948 	error = bwi_dma_alloc(sc);
949 	if (error)
950 		goto fail;
951 
952 	/* setup interface */
953 	ifp->if_softc = sc;
954 	ifp->if_init = bwi_init;
955 	ifp->if_ioctl = bwi_ioctl;
956 	ifp->if_start = bwi_start;
957 	ifp->if_watchdog = bwi_watchdog;
958 	ifp->if_stop = bwi_stop;
959 	ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
960 	memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
961 	IFQ_SET_READY(&ifp->if_snd);
962 
963 	/* Get locale */
964 	sc->sc_locale = __SHIFTOUT(bwi_read_sprom(sc, BWI_SPROM_CARD_INFO),
965 	    BWI_SPROM_CARD_INFO_LOCALE);
966 	DPRINTF(sc, BWI_DBG_ATTACH, "locale: %d\n", sc->sc_locale);
967 
968 	/*
969 	 * Setup ratesets, phytype, channels and get MAC address
970 	 */
971 	if (phy->phy_mode == IEEE80211_MODE_11B ||
972 	    phy->phy_mode == IEEE80211_MODE_11G) {
973 		uint16_t chan_flags;
974 
975 		ic->ic_sup_rates[IEEE80211_MODE_11B] =
976 		    ieee80211_std_rateset_11b;
977 
978 		if (phy->phy_mode == IEEE80211_MODE_11B) {
979 			chan_flags = IEEE80211_CHAN_B;
980 			ic->ic_phytype = IEEE80211_T_DS;
981 		} else {
982 			chan_flags = IEEE80211_CHAN_CCK |
983 			    IEEE80211_CHAN_OFDM |
984 			    IEEE80211_CHAN_DYN |
985 			    IEEE80211_CHAN_2GHZ;
986 			ic->ic_phytype = IEEE80211_T_OFDM;
987 			ic->ic_sup_rates[IEEE80211_MODE_11G] =
988 			    ieee80211_std_rateset_11g;
989 		}
990 
991 		/* XXX depend on locale */
992 		for (i = 1; i <= 14; ++i) {
993 			ic->ic_channels[i].ic_freq =
994 			    ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
995 			ic->ic_channels[i].ic_flags = chan_flags;
996 		}
997 
998 		bwi_get_eaddr(sc, BWI_SPROM_11BG_EADDR, ic->ic_myaddr);
999 		if (IEEE80211_IS_MULTICAST(ic->ic_myaddr)) {
1000 			bwi_get_eaddr(sc, BWI_SPROM_11A_EADDR, ic->ic_myaddr);
1001 			if (IEEE80211_IS_MULTICAST(ic->ic_myaddr))
1002 				aprint_error_dev(sc->sc_dev,
1003 				    "invalid MAC address: %s\n",
1004 				    ether_sprintf(ic->ic_myaddr));
1005 		}
1006 	} else if (phy->phy_mode == IEEE80211_MODE_11A) {
1007 		/* TODO: 11A */
1008 		error = ENXIO;
1009 		goto fail;
1010 	} else
1011 		panic("unknown phymode %d\n", phy->phy_mode);
1012 
1013 	ic->ic_ifp = ifp;
1014 	ic->ic_caps = IEEE80211_C_SHSLOT |
1015 	    IEEE80211_C_SHPREAMBLE |
1016 	    IEEE80211_C_IBSS |
1017 	    IEEE80211_C_HOSTAP |
1018 	    IEEE80211_C_MONITOR;
1019 	ic->ic_state = IEEE80211_S_INIT;
1020 	ic->ic_opmode = IEEE80211_M_STA;
1021 
1022 	ic->ic_updateslot = bwi_updateslot;
1023 
1024 	error = if_initialize(ifp);
1025 	if (error != 0) {
1026 		aprint_error_dev(sc->sc_dev, "if_initialize failed(%d)\n",
1027 		    error);
1028 		goto fail;
1029 	}
1030 	ieee80211_ifattach(ic);
1031 	ifp->if_percpuq = if_percpuq_create(ifp);
1032 	if_register(ifp);
1033 
1034 	/* [TRC: XXX Not supported on NetBSD?] */
1035 	/* ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS; */
1036 
1037 	sc->sc_newstate = ic->ic_newstate;
1038 	ic->ic_newstate = bwi_newstate;
1039 	/* [TRC: XXX amrr] */
1040 	ic->ic_newassoc = bwi_newassoc;
1041 	ic->ic_node_alloc = bwi_node_alloc;
1042 
1043 	ieee80211_media_init(ic, bwi_media_change, ieee80211_media_status);
1044 
1045 	bpf_attach2(ifp, DLT_IEEE802_11_RADIO,
1046 	    sizeof(struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN,
1047 	    &sc->sc_drvbpf);
1048 
1049 	/* [TRC: XXX DragonFlyBSD rounds this up to a multiple of
1050 	   sizeof(uint32_t).  Should we?] */
1051 	sc->sc_rxtap_len = sizeof(sc->sc_rxtapu);
1052 	sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
1053 	sc->sc_rxtap.wr_ihdr.it_present = htole32(BWI_RX_RADIOTAP_PRESENT);
1054 
1055 	sc->sc_txtap_len = sizeof(sc->sc_txtapu);
1056 	sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
1057 	sc->sc_txtap.wt_ihdr.it_present = htole32(BWI_TX_RADIOTAP_PRESENT);
1058 
1059 	splx(s);
1060 	ieee80211_announce(ic);
1061 	return (0);
1062 fail:
1063 	/* [TRC: XXX DragonFlyBSD detaches the device here.  Should we?] */
1064 	splx(s);
1065 	return (error);
1066 }
1067 
1068 void
1069 bwi_detach(struct bwi_softc *sc)
1070 {
1071 	struct ifnet *ifp = &sc->sc_if;
1072 	int i, s;
1073 
1074 	s = splnet();
1075 
1076 	bwi_stop(ifp, 1);
1077 
1078 	bpf_detach(ifp);
1079 
1080 	ieee80211_ifdetach(&sc->sc_ic);
1081 	if_detach(ifp);
1082 
1083 	for (i = 0; i < sc->sc_nmac; ++i)
1084 		bwi_mac_detach(&sc->sc_mac[i]);
1085 
1086 	sysctl_teardown(&sc->sc_sysctllog);
1087 
1088 	if (sc->sc_soft_ih != NULL)
1089 		softint_disestablish(sc->sc_soft_ih);
1090 
1091 	splx(s);
1092 
1093 	bwi_dma_free(sc);
1094 }
1095 
1096 /* MAC */
1097 
1098 static void
1099 bwi_tmplt_write_4(struct bwi_mac *mac, uint32_t ofs, uint32_t val)
1100 {
1101 	struct bwi_softc *sc = mac->mac_sc;
1102 
1103 	if (mac->mac_flags & BWI_MAC_F_BSWAP)
1104 		val = bswap32(val);
1105 
1106 	CSR_WRITE_4(sc, BWI_MAC_TMPLT_CTRL, ofs);
1107 	CSR_WRITE_4(sc, BWI_MAC_TMPLT_DATA, val);
1108 }
1109 
1110 static void
1111 bwi_hostflags_write(struct bwi_mac *mac, uint64_t flags)
1112 {
1113 	uint64_t val;
1114 
1115 	val = flags & 0xffff;
1116 	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_LO, val);
1117 
1118 	val = (flags >> 16) & 0xffff;
1119 	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_MI, val);
1120 
1121 	/* HI has unclear meaning, so leave it as it is */
1122 }
1123 
1124 static uint64_t
1125 bwi_hostflags_read(struct bwi_mac *mac)
1126 {
1127 	uint64_t flags, val;
1128 
1129 	/* HI has unclear meaning, so don't touch it */
1130 	flags = 0;
1131 
1132 	val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_MI);
1133 	flags |= val << 16;
1134 
1135 	val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_LO);
1136 	flags |= val;
1137 
1138 	return (flags);
1139 }
1140 
1141 static uint16_t
1142 bwi_memobj_read_2(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0)
1143 {
1144 	struct bwi_softc *sc = mac->mac_sc;
1145 	uint32_t data_reg;
1146 	int ofs;
1147 
1148 	data_reg = BWI_MOBJ_DATA;
1149 	ofs = ofs0 / 4;
1150 
1151 	if (ofs0 % 4 != 0)
1152 		data_reg = BWI_MOBJ_DATA_UNALIGN;
1153 
1154 	CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
1155 	return (CSR_READ_2(sc, data_reg));
1156 }
1157 
1158 static uint32_t
1159 bwi_memobj_read_4(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0)
1160 {
1161 	struct bwi_softc *sc = mac->mac_sc;
1162 	int ofs;
1163 
1164 	ofs = ofs0 / 4;
1165 	if (ofs0 % 4 != 0) {
1166 		uint32_t ret;
1167 
1168 		CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
1169 		ret = CSR_READ_2(sc, BWI_MOBJ_DATA_UNALIGN);
1170 		ret <<= 16;
1171 
1172 		CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
1173 		    BWI_MOBJ_CTRL_VAL(obj_id, ofs + 1));
1174 		ret |= CSR_READ_2(sc, BWI_MOBJ_DATA);
1175 
1176 		return (ret);
1177 	} else {
1178 		CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
1179 		return (CSR_READ_4(sc, BWI_MOBJ_DATA));
1180 	}
1181 }
1182 
1183 static void
1184 bwi_memobj_write_2(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0,
1185     uint16_t v)
1186 {
1187 	struct bwi_softc *sc = mac->mac_sc;
1188 	uint32_t data_reg;
1189 	int ofs;
1190 
1191 	data_reg = BWI_MOBJ_DATA;
1192 	ofs = ofs0 / 4;
1193 
1194 	if (ofs0 % 4 != 0)
1195 		data_reg = BWI_MOBJ_DATA_UNALIGN;
1196 
1197 	CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
1198 	CSR_WRITE_2(sc, data_reg, v);
1199 }
1200 
1201 static void
1202 bwi_memobj_write_4(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0,
1203     uint32_t v)
1204 {
1205 	struct bwi_softc *sc = mac->mac_sc;
1206 	int ofs;
1207 
1208 	ofs = ofs0 / 4;
1209 	if (ofs0 % 4 != 0) {
1210 		CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
1211 		CSR_WRITE_2(sc, BWI_MOBJ_DATA_UNALIGN, v >> 16);
1212 		CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
1213 		    BWI_MOBJ_CTRL_VAL(obj_id, ofs + 1));
1214 		CSR_WRITE_2(sc, BWI_MOBJ_DATA, v & 0xffff);
1215 	} else {
1216 		CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs));
1217 		CSR_WRITE_4(sc, BWI_MOBJ_DATA, v);
1218 	}
1219 }
1220 
1221 static int
1222 bwi_mac_lateattach(struct bwi_mac *mac)
1223 {
1224 	int error;
1225 
1226 	if (mac->mac_rev >= 5)
1227 		CSR_READ_4(mac->mac_sc, BWI_STATE_HI); /* dummy read */
1228 
1229 	bwi_mac_reset(mac, 1);
1230 
1231 	error = bwi_phy_attach(mac);
1232 	if (error)
1233 		return (error);
1234 
1235 	error = bwi_rf_attach(mac);
1236 	if (error)
1237 		return (error);
1238 
1239 	/* Link 11B/G PHY, unlink 11A PHY */
1240 	if (mac->mac_phy.phy_mode == IEEE80211_MODE_11A)
1241 		bwi_mac_reset(mac, 0);
1242 	else
1243 		bwi_mac_reset(mac, 1);
1244 
1245 	error = bwi_mac_test(mac);
1246 	if (error)
1247 		return (error);
1248 
1249 	error = bwi_mac_get_property(mac);
1250 	if (error)
1251 		return (error);
1252 
1253 	error = bwi_rf_map_txpower(mac);
1254 	if (error)
1255 		return (error);
1256 
1257 	bwi_rf_off(mac);
1258 	CSR_WRITE_2(mac->mac_sc, BWI_BBP_ATTEN, BWI_BBP_ATTEN_MAGIC);
1259 	bwi_regwin_disable(mac->mac_sc, &mac->mac_regwin, 0);
1260 
1261 	return (0);
1262 }
1263 
1264 static int
1265 bwi_mac_init(struct bwi_mac *mac)
1266 {
1267 	struct bwi_softc *sc = mac->mac_sc;
1268 	int error, i;
1269 
1270 	/* Clear MAC/PHY/RF states */
1271 	bwi_mac_setup_tpctl(mac);
1272 	bwi_rf_clear_state(&mac->mac_rf);
1273 	bwi_phy_clear_state(&mac->mac_phy);
1274 
1275 	/* Enable MAC and linked it to PHY */
1276 	if (!bwi_regwin_is_enabled(sc, &mac->mac_regwin))
1277 		bwi_mac_reset(mac, 1);
1278 
1279 	/* Initialize backplane */
1280 	error = bwi_bus_init(sc, mac);
1281 	if (error)
1282 		return (error);
1283 
1284 	/* XXX work around for hardware bugs? */
1285 	if (sc->sc_bus_regwin.rw_rev <= 5 &&
1286 	    sc->sc_bus_regwin.rw_type != BWI_REGWIN_T_BUSPCIE) {
1287 		CSR_SETBITS_4(sc, BWI_CONF_LO,
1288 		__SHIFTIN(BWI_CONF_LO_SERVTO, BWI_CONF_LO_SERVTO_MASK) |
1289 		__SHIFTIN(BWI_CONF_LO_REQTO, BWI_CONF_LO_REQTO_MASK));
1290 	}
1291 
1292 	/* Calibrate PHY */
1293 	error = bwi_phy_calibrate(mac);
1294 	if (error) {
1295 		aprint_error_dev(sc->sc_dev, "PHY calibrate failed\n");
1296 		return (error);
1297 	}
1298 
1299 	/* Prepare to initialize firmware */
1300 	CSR_WRITE_4(sc, BWI_MAC_STATUS,
1301 	    BWI_MAC_STATUS_UCODE_JUMP0 |
1302 	    BWI_MAC_STATUS_IHREN);
1303 
1304 	/*
1305 	 * Load and initialize firmwares
1306 	 */
1307 	error = bwi_mac_fw_alloc(mac);
1308 	if (error)
1309 		return (error);
1310 
1311 	error = bwi_mac_fw_load(mac);
1312 	if (error)
1313 		return (error);
1314 
1315 	error = bwi_mac_gpio_init(mac);
1316 	if (error)
1317 		return (error);
1318 
1319 	error = bwi_mac_fw_init(mac);
1320 	if (error)
1321 		return (error);
1322 
1323 	/*
1324 	 * Turn on RF
1325 	 */
1326 	bwi_rf_on(mac);
1327 
1328 	/* TODO: LED, hardware rf enabled is only related to LED setting */
1329 
1330 	/*
1331 	 * Initialize PHY
1332 	 */
1333 	CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0);
1334 	bwi_phy_init(mac);
1335 
1336 	/* TODO: interference mitigation */
1337 
1338 	/*
1339 	 * Setup antenna mode
1340 	 */
1341 	bwi_rf_set_ant_mode(mac, mac->mac_rf.rf_ant_mode);
1342 
1343 	/*
1344 	 * Initialize operation mode (RX configuration)
1345 	 */
1346 	bwi_mac_opmode_init(mac);
1347 
1348 	/* XXX what's these */
1349 	if (mac->mac_rev < 3) {
1350 		CSR_WRITE_2(sc, 0x60e, 0);
1351 		CSR_WRITE_2(sc, 0x610, 0x8000);
1352 		CSR_WRITE_2(sc, 0x604, 0);
1353 		CSR_WRITE_2(sc, 0x606, 0x200);
1354 	} else {
1355 		CSR_WRITE_4(sc, 0x188, 0x80000000);
1356 		CSR_WRITE_4(sc, 0x18c, 0x2000000);
1357 	}
1358 
1359 	/*
1360 	 * Initialize TX/RX interrupts' mask
1361 	 */
1362 	CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_INTR_TIMER1);
1363 	for (i = 0; i < BWI_TXRX_NRING; ++i) {
1364 		uint32_t intrs;
1365 
1366 		if (BWI_TXRX_IS_RX(i))
1367 			intrs = BWI_TXRX_RX_INTRS;
1368 		else
1369 			intrs = BWI_TXRX_TX_INTRS;
1370 		CSR_WRITE_4(sc, BWI_TXRX_INTR_MASK(i), intrs);
1371 	}
1372 
1373 	/* XXX what's this */
1374 	CSR_SETBITS_4(sc, BWI_STATE_LO, 0x100000);
1375 
1376 	/* Setup MAC power up delay */
1377 	CSR_WRITE_2(sc, BWI_MAC_POWERUP_DELAY, sc->sc_pwron_delay);
1378 
1379 	/* Set MAC regwin revision */
1380 	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_MACREV, mac->mac_rev);
1381 
1382 	/*
1383 	 * Initialize host flags
1384 	 */
1385 	bwi_mac_hostflags_init(mac);
1386 
1387 	/*
1388 	 * Initialize BSS parameters
1389 	 */
1390 	bwi_mac_bss_param_init(mac);
1391 
1392 	/*
1393 	 * Initialize TX rings
1394 	 */
1395 	for (i = 0; i < BWI_TX_NRING; ++i) {
1396 		error = (sc->sc_init_tx_ring)(sc, i);
1397 		if (error) {
1398 			aprint_error_dev(sc->sc_dev,
1399 			    "can't initialize %dth TX ring\n", i);
1400 			return (error);
1401 		}
1402 	}
1403 
1404 	/*
1405 	 * Initialize RX ring
1406 	 */
1407 	error = (sc->sc_init_rx_ring)(sc);
1408 	if (error) {
1409 		aprint_error_dev(sc->sc_dev, "can't initialize RX ring\n");
1410 		return (error);
1411 	}
1412 
1413 	/*
1414 	 * Initialize TX stats if the current MAC uses that
1415 	 */
1416 	if (mac->mac_flags & BWI_MAC_F_HAS_TXSTATS) {
1417 		error = (sc->sc_init_txstats)(sc);
1418 		if (error) {
1419 			aprint_error_dev(sc->sc_dev,
1420 			    "can't initialize TX stats ring\n");
1421 			return (error);
1422 		}
1423 	}
1424 
1425 	/* XXX what's these */
1426 	CSR_WRITE_2(sc, 0x612, 0x50);	/* Force Pre-TBTT to 80? */
1427 	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, 0x416, 0x50);
1428 	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, 0x414, 0x1f4);
1429 
1430 	mac->mac_flags |= BWI_MAC_F_INITED;
1431 
1432 	return (0);
1433 }
1434 
1435 static void
1436 bwi_mac_reset(struct bwi_mac *mac, int link_phy)
1437 {
1438 	struct bwi_softc *sc = mac->mac_sc;
1439 	uint32_t flags, state_lo, status;
1440 
1441 	flags = BWI_STATE_LO_FLAG_PHYRST | BWI_STATE_LO_FLAG_PHYCLKEN;
1442 	if (link_phy)
1443 		flags |= BWI_STATE_LO_FLAG_PHYLNK;
1444 	bwi_regwin_enable(sc, &mac->mac_regwin, flags);
1445 	DELAY(2000);
1446 
1447 	state_lo = CSR_READ_4(sc, BWI_STATE_LO);
1448 	state_lo |= BWI_STATE_LO_GATED_CLOCK;
1449 	state_lo &= ~__SHIFTIN(BWI_STATE_LO_FLAG_PHYRST,
1450 			       BWI_STATE_LO_FLAGS_MASK);
1451 	CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
1452 	/* Flush pending bus write */
1453 	CSR_READ_4(sc, BWI_STATE_LO);
1454 	DELAY(1000);
1455 
1456 	state_lo &= ~BWI_STATE_LO_GATED_CLOCK;
1457 	CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
1458 	/* Flush pending bus write */
1459 	CSR_READ_4(sc, BWI_STATE_LO);
1460 	DELAY(1000);
1461 
1462 	CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0);
1463 
1464 	status = CSR_READ_4(sc, BWI_MAC_STATUS);
1465 	status |= BWI_MAC_STATUS_IHREN;
1466 	if (link_phy)
1467 		status |= BWI_MAC_STATUS_PHYLNK;
1468 	else
1469 		status &= ~BWI_MAC_STATUS_PHYLNK;
1470 	CSR_WRITE_4(sc, BWI_MAC_STATUS, status);
1471 
1472 	if (link_phy) {
1473 		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH | BWI_DBG_INIT,
1474 		    "%s\n", "PHY is linked");
1475 		mac->mac_phy.phy_flags |= BWI_PHY_F_LINKED;
1476 	} else {
1477 		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH | BWI_DBG_INIT,
1478 		    "%s\n", "PHY is unlinked");
1479 		mac->mac_phy.phy_flags &= ~BWI_PHY_F_LINKED;
1480 	}
1481 }
1482 
1483 static void
1484 bwi_mac_set_tpctl_11bg(struct bwi_mac *mac, const struct bwi_tpctl *new_tpctl)
1485 {
1486 	struct bwi_rf *rf = &mac->mac_rf;
1487 	struct bwi_tpctl *tpctl = &mac->mac_tpctl;
1488 
1489 	if (new_tpctl != NULL) {
1490 		KASSERT(new_tpctl->bbp_atten <= BWI_BBP_ATTEN_MAX);
1491 		KASSERT(new_tpctl->rf_atten <=
1492 		    (rf->rf_rev < 6 ? BWI_RF_ATTEN_MAX0
1493 		    : BWI_RF_ATTEN_MAX1));
1494 		KASSERT(new_tpctl->tp_ctrl1 <= BWI_TPCTL1_MAX);
1495 
1496 		tpctl->bbp_atten = new_tpctl->bbp_atten;
1497 		tpctl->rf_atten = new_tpctl->rf_atten;
1498 		tpctl->tp_ctrl1 = new_tpctl->tp_ctrl1;
1499 	}
1500 
1501 	/* Set BBP attenuation */
1502 	bwi_phy_set_bbp_atten(mac, tpctl->bbp_atten);
1503 
1504 	/* Set RF attenuation */
1505 	RF_WRITE(mac, BWI_RFR_ATTEN, tpctl->rf_atten);
1506 	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_RF_ATTEN,
1507 	    tpctl->rf_atten);
1508 
1509 	/* Set TX power */
1510 	if (rf->rf_type == BWI_RF_T_BCM2050) {
1511 		RF_FILT_SETBITS(mac, BWI_RFR_TXPWR, ~BWI_RFR_TXPWR1_MASK,
1512 		    __SHIFTIN(tpctl->tp_ctrl1, BWI_RFR_TXPWR1_MASK));
1513 	}
1514 
1515 	/* Adjust RF Local Oscillator */
1516 	if (mac->mac_phy.phy_mode == IEEE80211_MODE_11G)
1517 		bwi_rf_lo_adjust(mac, tpctl);
1518 }
1519 
1520 static int
1521 bwi_mac_test(struct bwi_mac *mac)
1522 {
1523 	struct bwi_softc *sc = mac->mac_sc;
1524 	uint32_t orig_val, val;
1525 
1526 #define TEST_VAL1	0xaa5555aa
1527 #define TEST_VAL2	0x55aaaa55
1528 	/* Save it for later restoring */
1529 	orig_val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0);
1530 
1531 	/* Test 1 */
1532 	MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, TEST_VAL1);
1533 	val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0);
1534 	if (val != TEST_VAL1) {
1535 		aprint_error_dev(sc->sc_dev, "TEST1 failed\n");
1536 		return (ENXIO);
1537 	}
1538 
1539 	/* Test 2 */
1540 	MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, TEST_VAL2);
1541 	val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0);
1542 	if (val != TEST_VAL2) {
1543 		aprint_error_dev(sc->sc_dev, "TEST2 failed\n");
1544 		return (ENXIO);
1545 	}
1546 
1547 	/* Restore to the original value */
1548 	MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, orig_val);
1549 
1550 	val = CSR_READ_4(sc, BWI_MAC_STATUS);
1551 	if ((val & ~BWI_MAC_STATUS_PHYLNK) != BWI_MAC_STATUS_IHREN) {
1552 		aprint_error_dev(sc->sc_dev, "%s failed, MAC status 0x%08x\n",
1553 		    __func__, val);
1554 		return (ENXIO);
1555 	}
1556 
1557 	val = CSR_READ_4(sc, BWI_MAC_INTR_STATUS);
1558 	if (val != 0) {
1559 		aprint_error_dev(sc->sc_dev, "%s failed, intr status %08x\n",
1560 		    __func__, val);
1561 		return (ENXIO);
1562 	}
1563 #undef TEST_VAL2
1564 #undef TEST_VAL1
1565 
1566 	return (0);
1567 }
1568 
1569 static void
1570 bwi_mac_setup_tpctl(struct bwi_mac *mac)
1571 {
1572 	struct bwi_softc *sc = mac->mac_sc;
1573 	struct bwi_rf *rf = &mac->mac_rf;
1574 	struct bwi_phy *phy = &mac->mac_phy;
1575 	struct bwi_tpctl *tpctl = &mac->mac_tpctl;
1576 
1577 	/* Calc BBP attenuation */
1578 	if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev < 6)
1579 		tpctl->bbp_atten = 0;
1580 	else
1581 		tpctl->bbp_atten = 2;
1582 
1583 	/* Calc TX power CTRL1?? */
1584 	tpctl->tp_ctrl1 = 0;
1585 	if (rf->rf_type == BWI_RF_T_BCM2050) {
1586 		if (rf->rf_rev == 1)
1587 			tpctl->tp_ctrl1 = 3;
1588 		else if (rf->rf_rev < 6)
1589 			tpctl->tp_ctrl1 = 2;
1590 		else if (rf->rf_rev == 8)
1591 			tpctl->tp_ctrl1 = 1;
1592 	}
1593 
1594 	/* Empty TX power CTRL2?? */
1595 	tpctl->tp_ctrl2 = 0xffff;
1596 
1597 	/*
1598 	 * Calc RF attenuation
1599 	 */
1600 	if (phy->phy_mode == IEEE80211_MODE_11A) {
1601 		tpctl->rf_atten = 0x60;
1602 		goto back;
1603 	}
1604 
1605 	if (BWI_IS_BRCM_BCM4309G(sc) && sc->sc_pci_revid < 0x51) {
1606 		tpctl->rf_atten = sc->sc_pci_revid < 0x43 ? 2 : 3;
1607 		goto back;
1608 	}
1609 
1610 	tpctl->rf_atten = 5;
1611 
1612 	if (rf->rf_type != BWI_RF_T_BCM2050) {
1613 		if (rf->rf_type == BWI_RF_T_BCM2053 && rf->rf_rev == 1)
1614 			tpctl->rf_atten = 6;
1615 		goto back;
1616 	}
1617 
1618 	/*
1619 	 * NB: If we reaches here and the card is BRCM_BCM4309G,
1620 	 *     then the card's PCI revision must >= 0x51
1621 	 */
1622 
1623 	/* BCM2050 RF */
1624 	switch (rf->rf_rev) {
1625 	case 1:
1626 		if (phy->phy_mode == IEEE80211_MODE_11G) {
1627 			if (BWI_IS_BRCM_BCM4309G(sc) || BWI_IS_BRCM_BU4306(sc))
1628 				tpctl->rf_atten = 3;
1629 			else
1630 				tpctl->rf_atten = 1;
1631 		} else {
1632 			if (BWI_IS_BRCM_BCM4309G(sc))
1633 				tpctl->rf_atten = 7;
1634 			else
1635 				tpctl->rf_atten = 6;
1636 		}
1637 		break;
1638 	case 2:
1639 		if (phy->phy_mode == IEEE80211_MODE_11G) {
1640 			/*
1641 			 * NOTE: Order of following conditions is critical
1642 			 */
1643 			if (BWI_IS_BRCM_BCM4309G(sc))
1644 				tpctl->rf_atten = 3;
1645 			else if (BWI_IS_BRCM_BU4306(sc))
1646 				tpctl->rf_atten = 5;
1647 			else if (sc->sc_bbp_id == BWI_BBPID_BCM4320)
1648 				tpctl->rf_atten = 4;
1649 			else
1650 				tpctl->rf_atten = 3;
1651 		} else {
1652 			tpctl->rf_atten = 6;
1653 		}
1654 		break;
1655 	case 4:
1656 	case 5:
1657 		tpctl->rf_atten = 1;
1658 		break;
1659 	case 8:
1660 		tpctl->rf_atten = 0x1a;
1661 		break;
1662 	}
1663 back:
1664 	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_TXPOWER,
1665 	    "bbp atten: %u, rf atten: %u, ctrl1: %u, ctrl2: %u\n",
1666 	    tpctl->bbp_atten, tpctl->rf_atten,
1667 	    tpctl->tp_ctrl1, tpctl->tp_ctrl2);
1668 }
1669 
1670 static void
1671 bwi_mac_dummy_xmit(struct bwi_mac *mac)
1672 {
1673 #define PACKET_LEN	5
1674 	static const uint32_t	packet_11a[PACKET_LEN] =
1675 	    { 0x000201cc, 0x00d40000, 0x00000000, 0x01000000, 0x00000000 };
1676 	static const uint32_t	packet_11bg[PACKET_LEN] =
1677 	    { 0x000b846e, 0x00d40000, 0x00000000, 0x01000000, 0x00000000 };
1678 
1679 	struct bwi_softc *sc = mac->mac_sc;
1680 	struct bwi_rf *rf = &mac->mac_rf;
1681 	const uint32_t *packet;
1682 	uint16_t val_50c;
1683 	int wait_max, i;
1684 
1685 	if (mac->mac_phy.phy_mode == IEEE80211_MODE_11A) {
1686 		wait_max = 30;
1687 		packet = packet_11a;
1688 		val_50c = 1;
1689 	} else {
1690 		wait_max = 250;
1691 		packet = packet_11bg;
1692 		val_50c = 0;
1693 	}
1694 
1695 	for (i = 0; i < PACKET_LEN; ++i)
1696 		TMPLT_WRITE_4(mac, i * 4, packet[i]);
1697 
1698 	CSR_READ_4(sc, BWI_MAC_STATUS);	/* dummy read */
1699 
1700 	CSR_WRITE_2(sc, 0x568, 0);
1701 	CSR_WRITE_2(sc, 0x7c0, 0);
1702 	CSR_WRITE_2(sc, 0x50c, val_50c);
1703 	CSR_WRITE_2(sc, 0x508, 0);
1704 	CSR_WRITE_2(sc, 0x50a, 0);
1705 	CSR_WRITE_2(sc, 0x54c, 0);
1706 	CSR_WRITE_2(sc, 0x56a, 0x14);
1707 	CSR_WRITE_2(sc, 0x568, 0x826);
1708 	CSR_WRITE_2(sc, 0x500, 0);
1709 	CSR_WRITE_2(sc, 0x502, 0x30);
1710 
1711 	if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev <= 5)
1712 		RF_WRITE(mac, 0x51, 0x17);
1713 
1714 	for (i = 0; i < wait_max; ++i) {
1715 		if (CSR_READ_2(sc, 0x50e) & 0x80)
1716 			break;
1717 		DELAY(10);
1718 	}
1719 	for (i = 0; i < 10; ++i) {
1720 		if (CSR_READ_2(sc, 0x50e) & 0x400)
1721 			break;
1722 		DELAY(10);
1723 	}
1724 	for (i = 0; i < 10; ++i) {
1725 		if ((CSR_READ_2(sc, 0x690) & 0x100) == 0)
1726 			break;
1727 		DELAY(10);
1728 	}
1729 
1730 	if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev <= 5)
1731 		RF_WRITE(mac, 0x51, 0x37);
1732 #undef PACKET_LEN
1733 }
1734 
1735 static void
1736 bwi_mac_init_tpctl_11bg(struct bwi_mac *mac)
1737 {
1738 	struct bwi_softc *sc = mac->mac_sc;
1739 	struct bwi_phy *phy = &mac->mac_phy;
1740 	struct bwi_rf *rf = &mac->mac_rf;
1741 	struct bwi_tpctl tpctl_orig;
1742 	int restore_tpctl = 0;
1743 
1744 	KASSERT(phy->phy_mode != IEEE80211_MODE_11A);
1745 
1746 	if (BWI_IS_BRCM_BU4306(sc))
1747 		return;
1748 
1749 	PHY_WRITE(mac, 0x28, 0x8018);
1750 	CSR_CLRBITS_2(sc, BWI_BBP_ATTEN, 0x20);
1751 
1752 	if (phy->phy_mode == IEEE80211_MODE_11G) {
1753 		if ((phy->phy_flags & BWI_PHY_F_LINKED) == 0)
1754 			return;
1755 		PHY_WRITE(mac, 0x47a, 0xc111);
1756 	}
1757 	if (mac->mac_flags & BWI_MAC_F_TPCTL_INITED)
1758 		return;
1759 
1760 	if (phy->phy_mode == IEEE80211_MODE_11B && phy->phy_rev >= 2 &&
1761 	    rf->rf_type == BWI_RF_T_BCM2050) {
1762 		RF_SETBITS(mac, 0x76, 0x84);
1763 	} else {
1764 		struct bwi_tpctl tpctl;
1765 
1766 		/* Backup original TX power control variables */
1767 		memcpy(&tpctl_orig, &mac->mac_tpctl, sizeof(tpctl_orig));
1768 		restore_tpctl = 1;
1769 
1770 		memcpy(&tpctl, &mac->mac_tpctl, sizeof(tpctl));
1771 		tpctl.bbp_atten = 11;
1772 		tpctl.tp_ctrl1 = 0;
1773 #ifdef notyet
1774 		if (rf->rf_rev >= 6 && rf->rf_rev <= 8)
1775 			tpctl.rf_atten = 31;
1776 		else
1777 #endif
1778 			tpctl.rf_atten = 9;
1779 
1780 		bwi_mac_set_tpctl_11bg(mac, &tpctl);
1781 	}
1782 
1783 	bwi_mac_dummy_xmit(mac);
1784 
1785 	mac->mac_flags |= BWI_MAC_F_TPCTL_INITED;
1786 	rf->rf_base_tssi = PHY_READ(mac, 0x29);
1787 	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_TXPOWER,
1788 	    "base tssi %d\n", rf->rf_base_tssi);
1789 
1790 	if (abs(rf->rf_base_tssi - rf->rf_idle_tssi) >= 20) {
1791 		aprint_error_dev(sc->sc_dev, "base tssi measure failed\n");
1792 		mac->mac_flags |= BWI_MAC_F_TPCTL_ERROR;
1793 	}
1794 
1795 	if (restore_tpctl)
1796 		bwi_mac_set_tpctl_11bg(mac, &tpctl_orig);
1797 	else
1798 		RF_CLRBITS(mac, 0x76, 0x84);
1799 
1800 	bwi_rf_clear_tssi(mac);
1801 }
1802 
1803 static void
1804 bwi_mac_detach(struct bwi_mac *mac)
1805 {
1806 	bwi_mac_fw_free(mac);
1807 }
1808 
1809 static int
1810 bwi_mac_fw_alloc(struct bwi_mac *mac)
1811 {
1812 	struct bwi_softc *sc = mac->mac_sc;
1813 	int idx, error;
1814 
1815 	error = bwi_mac_fw_image_alloc(mac, BWI_FW_UCODE_PREFIX,
1816 	    mac->mac_rev >= 5 ? 5 : mac->mac_rev, &mac->mac_ucode_fwi,
1817 	    BWI_FW_T_UCODE);
1818 	if (error)
1819 		goto fail_ucode;
1820 
1821 	error = bwi_mac_fw_image_alloc(mac, BWI_FW_PCM_PREFIX,
1822 	    mac->mac_rev >= 5 ? 5 : mac->mac_rev, &mac->mac_pcm_fwi,
1823 	    BWI_FW_T_PCM);
1824 	if (error)
1825 		goto fail_pcm;
1826 
1827 	/* TODO: 11A */
1828 	if (mac->mac_rev == 2 || mac->mac_rev == 4)
1829 		idx = 2;
1830 	else if (mac->mac_rev >= 5 && mac->mac_rev <= 20)
1831 		idx = 5;
1832 	else {
1833 		aprint_error_dev(sc->sc_dev,
1834 		    "no suitable IV for MAC rev %d\n", mac->mac_rev);
1835 		error = ENODEV;
1836 		goto fail_iv;
1837 	}
1838 
1839 	error = bwi_mac_fw_image_alloc(mac, BWI_FW_IV_PREFIX, idx,
1840 	    &mac->mac_iv_fwi, BWI_FW_T_IV);
1841 	if (error)
1842 		goto fail_iv;
1843 
1844 	/* TODO: 11A */
1845 	if (mac->mac_rev == 2 || mac->mac_rev == 4 ||
1846 	    mac->mac_rev >= 11)
1847 		/* No extended IV */
1848 		goto back;
1849 	else if (mac->mac_rev >= 5 && mac->mac_rev <= 10)
1850 		idx = 5;
1851 	else {
1852 		aprint_error_dev(sc->sc_dev,
1853 		    "no suitable ExtIV for MAC rev %d\n", mac->mac_rev);
1854 		error = ENODEV;
1855 		goto fail_iv_ext;
1856 	}
1857 
1858 	error = bwi_mac_fw_image_alloc(mac, BWI_FW_IV_EXT_PREFIX, idx,
1859 	    &mac->mac_iv_ext_fwi, BWI_FW_T_IV);
1860 	if (error)
1861 		goto fail_iv_ext;
1862 
1863 back:	return (0);
1864 
1865 fail_iv_ext:
1866 	bwi_mac_fw_image_free(mac, &mac->mac_iv_fwi);
1867 
1868 fail_iv:
1869 	bwi_mac_fw_image_free(mac, &mac->mac_pcm_fwi);
1870 
1871 fail_pcm:
1872 	bwi_mac_fw_image_free(mac, &mac->mac_ucode_fwi);
1873 
1874 fail_ucode:
1875 	return (error);
1876 }
1877 
1878 static void
1879 bwi_mac_fw_free(struct bwi_mac *mac)
1880 {
1881 	bwi_mac_fw_image_free(mac, &mac->mac_ucode_fwi);
1882 	bwi_mac_fw_image_free(mac, &mac->mac_pcm_fwi);
1883 	bwi_mac_fw_image_free(mac, &mac->mac_iv_fwi);
1884 	bwi_mac_fw_image_free(mac, &mac->mac_iv_ext_fwi);
1885 }
1886 
1887 static int
1888 bwi_mac_fw_image_alloc(struct bwi_mac *mac, const char *prefix, int idx,
1889     struct bwi_fw_image *fwi, uint8_t fw_type)
1890 {
1891 	struct bwi_softc *sc = mac->mac_sc;
1892 	char *fw_name = fwi->fwi_name;
1893 	size_t fw_name_size = sizeof(fwi->fwi_name);
1894 	firmware_handle_t fwh;
1895 	const struct bwi_fwhdr *hdr;
1896 	int error;
1897 
1898 	/* [TRC: XXX ???] */
1899 	if (fwi->fwi_data != NULL)
1900 		return (0);
1901 
1902 	snprintf(fw_name, fw_name_size, BWI_FW_NAME_FORMAT, sc->sc_fw_version,
1903 	    prefix, idx);
1904 
1905 	DPRINTF(sc, BWI_DBG_FIRMWARE, "opening firmware %s\n", fw_name);
1906 
1907 	error = firmware_open("bwi", fw_name, &fwh);
1908 	if (error) {
1909 		aprint_error_dev(sc->sc_dev, "firmware_open failed on %s\n",
1910 		    fw_name);
1911 		goto fail;
1912 	}
1913 
1914 	fwi->fwi_size = firmware_get_size(fwh);
1915 	if (fwi->fwi_size < sizeof(struct bwi_fwhdr)) {
1916 		aprint_error_dev(sc->sc_dev,
1917 		    "firmware image %s has no header\n",
1918 		    fw_name);
1919 		error = EIO;
1920 		goto fail;
1921 	}
1922 
1923 	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_FIRMWARE,
1924 	    "firmware image %s, size %zx\n", fw_name, fwi->fwi_size);
1925 
1926 	fwi->fwi_data = firmware_malloc(fwi->fwi_size);
1927 	if (fwi->fwi_data == NULL) {
1928 		error = ENOMEM;
1929 		firmware_close(fwh);
1930 		goto fail;
1931 	}
1932 
1933 	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_FIRMWARE,
1934 	    "firmware image %s loaded at %p\n", fw_name, fwi->fwi_data);
1935 
1936 	fwi->fwi_data = firmware_malloc(fwi->fwi_size);
1937 	error = firmware_read(fwh, 0, fwi->fwi_data, fwi->fwi_size);
1938 	firmware_close(fwh);
1939 	if (error)
1940 		goto free_and_fail;
1941 
1942 	hdr = (const struct bwi_fwhdr *)fwi->fwi_data;
1943 
1944 	if (fw_type != BWI_FW_T_IV) {
1945 		/*
1946 		 * Don't verify IV's size, it has different meaning
1947 		 */
1948 		size_t fw_size = (size_t)be32toh(hdr->fw_size);
1949 		if (fw_size != fwi->fwi_size - sizeof(*hdr)) {
1950 			aprint_error_dev(sc->sc_dev, "firmware image %s"
1951 			    " size mismatch, fw %zx, real %zx\n", fw_name,
1952 			    fw_size, fwi->fwi_size - sizeof(*hdr));
1953 			goto invalid;
1954 		}
1955 	}
1956 
1957 	if (hdr->fw_type != fw_type) {
1958 		aprint_error_dev(sc->sc_dev, "firmware image %s"
1959 		    " type mismatch, fw `%c', target `%c'\n", fw_name,
1960 		    hdr->fw_type, fw_type);
1961 		goto invalid;
1962 	}
1963 
1964 	if (hdr->fw_gen != BWI_FW_GEN_1) {
1965 		aprint_error_dev(sc->sc_dev, "firmware image %s"
1966 		    " generation mismatch, fw %d, target %d\n", fw_name,
1967 		    hdr->fw_gen, BWI_FW_GEN_1);
1968 		goto invalid;
1969 	}
1970 
1971 	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_FIRMWARE,
1972 	    "firmware image %s loaded successfully\n", fw_name);
1973 
1974 	return (0);
1975 
1976 invalid:
1977 	error = EINVAL;
1978 
1979 free_and_fail:
1980 	firmware_free(fwi->fwi_data, fwi->fwi_size);
1981 	fwi->fwi_data = NULL;
1982 	fwi->fwi_size = 0;
1983 
1984 fail:
1985 	return (error);
1986 }
1987 
1988 static void
1989 bwi_mac_fw_image_free(struct bwi_mac *mac, struct bwi_fw_image *fwi)
1990 {
1991 	if (fwi->fwi_data != NULL) {
1992 		DPRINTF(mac->mac_sc, BWI_DBG_FIRMWARE, "freeing firmware %s\n",
1993 		    fwi->fwi_name);
1994 		firmware_free(fwi->fwi_data, fwi->fwi_size);
1995 		fwi->fwi_data = NULL;
1996 		fwi->fwi_size = 0;
1997 	}
1998 }
1999 
2000 static int
2001 bwi_mac_fw_load(struct bwi_mac *mac)
2002 {
2003 	struct bwi_softc *sc = mac->mac_sc;
2004 	const uint32_t *fw;
2005 	uint16_t fw_rev;
2006 	size_t fw_len, i;
2007 
2008 	/*
2009 	 * Load ucode image
2010 	 */
2011 	fw = (const uint32_t *)(mac->mac_ucode + BWI_FWHDR_SZ);
2012 	fw_len = (mac->mac_ucode_size - BWI_FWHDR_SZ) / sizeof(uint32_t);
2013 
2014 	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_FIRMWARE,
2015 	    "loading ucode image at %p, length %zx\n",
2016 	    fw, fw_len);
2017 
2018 	CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
2019 	    BWI_MOBJ_CTRL_VAL(BWI_FW_UCODE_MOBJ | BWI_WR_MOBJ_AUTOINC, 0));
2020 	for (i = 0; i < fw_len; ++i) {
2021 		CSR_WRITE_4(sc, BWI_MOBJ_DATA, be32toh(fw[i]));
2022 		DELAY(10);
2023 	}
2024 
2025 	/*
2026 	 * Load PCM image
2027 	 */
2028 	fw = (const uint32_t *)(mac->mac_pcm + BWI_FWHDR_SZ);
2029 	fw_len = (mac->mac_pcm_size - BWI_FWHDR_SZ) / sizeof(uint32_t);
2030 
2031 	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_FIRMWARE,
2032 	    "loading PCM image at %p, length %zx\n",
2033 	    fw, fw_len);
2034 
2035 	CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
2036 	    BWI_MOBJ_CTRL_VAL(BWI_FW_PCM_MOBJ, 0x01ea));
2037 	CSR_WRITE_4(sc, BWI_MOBJ_DATA, 0x4000);
2038 
2039 	CSR_WRITE_4(sc, BWI_MOBJ_CTRL,
2040 	    BWI_MOBJ_CTRL_VAL(BWI_FW_PCM_MOBJ, 0x01eb));
2041 	for (i = 0; i < fw_len; ++i) {
2042 		CSR_WRITE_4(sc, BWI_MOBJ_DATA, be32toh(fw[i]));
2043 		DELAY(10);
2044 	}
2045 
2046 	CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_ALL_INTRS);
2047 	CSR_WRITE_4(sc, BWI_MAC_STATUS,
2048 	    BWI_MAC_STATUS_UCODE_START |
2049 	    BWI_MAC_STATUS_IHREN |
2050 	    BWI_MAC_STATUS_INFRA);
2051 #define NRETRY	200
2052 	for (i = 0; i < NRETRY; ++i) {
2053 		uint32_t intr_status;
2054 
2055 		intr_status = CSR_READ_4(sc, BWI_MAC_INTR_STATUS);
2056 		if (intr_status == BWI_INTR_READY)
2057 			break;
2058 		DELAY(10);
2059 	}
2060 	if (i == NRETRY) {
2061 		aprint_error_dev(sc->sc_dev,
2062 		    "timeout loading ucode & pcm firmware\n");
2063 		return (ETIMEDOUT);
2064 	}
2065 #undef NRETRY
2066 
2067 	CSR_READ_4(sc, BWI_MAC_INTR_STATUS);	/* dummy read */
2068 
2069 	fw_rev = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWREV);
2070 	if (fw_rev > BWI_FW_VERSION3_REVMAX) {
2071 		aprint_error_dev(sc->sc_dev,
2072 		    "firmware version 4 is not supported yet\n");
2073 		return (ENODEV);
2074 	}
2075 
2076 	aprint_normal_dev(sc->sc_dev, "firmware rev 0x%04x,"
2077 	    " patch level 0x%04x\n", fw_rev,
2078 	    MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWPATCHLV));
2079 
2080 	return (0);
2081 }
2082 
2083 static int
2084 bwi_mac_gpio_init(struct bwi_mac *mac)
2085 {
2086 	struct bwi_softc *sc = mac->mac_sc;
2087 	struct bwi_regwin *old, *gpio_rw;
2088 	uint32_t filt, bits;
2089 	int error;
2090 
2091 	CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_GPOSEL_MASK);
2092 	/* TODO: LED */
2093 
2094 	CSR_SETBITS_2(sc, BWI_MAC_GPIO_MASK, 0xf);
2095 
2096 	filt = 0x1f;
2097 	bits = 0xf;
2098 	if (sc->sc_bbp_id == BWI_BBPID_BCM4301) {
2099 		filt |= 0x60;
2100 		bits |= 0x60;
2101 	}
2102 	if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) {
2103 		CSR_SETBITS_2(sc, BWI_MAC_GPIO_MASK, 0x200);
2104 		filt |= 0x200;
2105 		bits |= 0x200;
2106 	}
2107 
2108 	gpio_rw = BWI_GPIO_REGWIN(sc);
2109 	error = bwi_regwin_switch(sc, gpio_rw, &old);
2110 	if (error)
2111 		return (error);
2112 
2113 	CSR_FILT_SETBITS_4(sc, BWI_GPIO_CTRL, filt, bits);
2114 
2115 	return (bwi_regwin_switch(sc, old, NULL));
2116 }
2117 
2118 static int
2119 bwi_mac_gpio_fini(struct bwi_mac *mac)
2120 {
2121 	struct bwi_softc *sc = mac->mac_sc;
2122 	struct bwi_regwin *old, *gpio_rw;
2123 	int error;
2124 
2125 	gpio_rw = BWI_GPIO_REGWIN(sc);
2126 	error = bwi_regwin_switch(sc, gpio_rw, &old);
2127 	if (error)
2128 		return (error);
2129 
2130 	CSR_WRITE_4(sc, BWI_GPIO_CTRL, 0);
2131 
2132 	return (bwi_regwin_switch(sc, old, NULL));
2133 }
2134 
2135 static int
2136 bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct bwi_fw_image *fwi)
2137 {
2138 	struct bwi_softc *sc = mac->mac_sc;
2139 	const struct bwi_fwhdr *hdr;
2140 	const struct bwi_fw_iv *iv;
2141 	size_t iv_img_size;
2142 	int n, i;
2143 
2144 	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_FIRMWARE,
2145 	    "loading %s at %p\n", fwi->fwi_name, fwi->fwi_data);
2146 
2147 	/* Get the number of IVs in the IV image */
2148 	hdr = (const struct bwi_fwhdr *)fwi->fwi_data;
2149 	n = be32toh(hdr->fw_iv_cnt);
2150 	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_INIT | BWI_DBG_FIRMWARE,
2151 	    "IV count %d\n", n);
2152 
2153 	/* Calculate the IV image size, for later sanity check */
2154 	iv_img_size = fwi->fwi_size - sizeof(*hdr);
2155 
2156 	/* Locate the first IV */
2157 	iv = (const struct bwi_fw_iv *)(fwi->fwi_data + sizeof(*hdr));
2158 
2159 	for (i = 0; i < n; ++i) {
2160 		uint16_t iv_ofs, ofs;
2161 		int sz = 0;
2162 
2163 		if (iv_img_size < sizeof(iv->iv_ofs)) {
2164 			aprint_error_dev(sc->sc_dev,
2165 			    "invalid IV image, ofs\n");
2166 			return (EINVAL);
2167 		}
2168 		iv_img_size -= sizeof(iv->iv_ofs);
2169 		sz += sizeof(iv->iv_ofs);
2170 
2171 		iv_ofs = be16toh(iv->iv_ofs);
2172 
2173 		ofs = __SHIFTOUT(iv_ofs, BWI_FW_IV_OFS_MASK);
2174 		if (ofs >= 0x1000) {
2175 			aprint_error_dev(sc->sc_dev, "invalid ofs (0x%04x) "
2176 			    "for %dth iv\n", ofs, i);
2177 			return (EINVAL);
2178 		}
2179 
2180 		if (iv_ofs & BWI_FW_IV_IS_32BIT) {
2181 			uint32_t val32;
2182 
2183 			if (iv_img_size < sizeof(iv->iv_val.val32)) {
2184 				aprint_error_dev(sc->sc_dev,
2185 				    "invalid IV image, val32\n");
2186 				return (EINVAL);
2187 			}
2188 			iv_img_size -= sizeof(iv->iv_val.val32);
2189 			sz += sizeof(iv->iv_val.val32);
2190 
2191 			val32 = be32toh(iv->iv_val.val32);
2192 			CSR_WRITE_4(sc, ofs, val32);
2193 		} else {
2194 			uint16_t val16;
2195 
2196 			if (iv_img_size < sizeof(iv->iv_val.val16)) {
2197 				aprint_error_dev(sc->sc_dev,
2198 				    "invalid IV image, val16\n");
2199 				return (EINVAL);
2200 			}
2201 			iv_img_size -= sizeof(iv->iv_val.val16);
2202 			sz += sizeof(iv->iv_val.val16);
2203 
2204 			val16 = be16toh(iv->iv_val.val16);
2205 			CSR_WRITE_2(sc, ofs, val16);
2206 		}
2207 
2208 		iv = (const struct bwi_fw_iv *)((const uint8_t *)iv + sz);
2209 	}
2210 
2211 	if (iv_img_size != 0) {
2212 		aprint_error_dev(sc->sc_dev,
2213 		    "invalid IV image, size left %zx\n", iv_img_size);
2214 		return (EINVAL);
2215 	}
2216 
2217 	return (0);
2218 }
2219 
2220 static int
2221 bwi_mac_fw_init(struct bwi_mac *mac)
2222 {
2223 	struct bwi_softc *sc = mac->mac_sc;
2224 	int error;
2225 
2226 	error = bwi_mac_fw_load_iv(mac, &mac->mac_iv_fwi);
2227 	if (error) {
2228 		aprint_error_dev(sc->sc_dev, "load IV failed\n");
2229 		return (error);
2230 	}
2231 
2232 	if (mac->mac_iv_ext != NULL) {
2233 		error = bwi_mac_fw_load_iv(mac, &mac->mac_iv_ext_fwi);
2234 		if (error)
2235 			aprint_error_dev(sc->sc_dev, "load ExtIV failed\n");
2236 	}
2237 
2238 	return (error);
2239 }
2240 
2241 static void
2242 bwi_mac_opmode_init(struct bwi_mac *mac)
2243 {
2244 	struct bwi_softc *sc = mac->mac_sc;
2245 	struct ieee80211com *ic = &sc->sc_ic;
2246 	uint32_t mac_status;
2247 	uint16_t pre_tbtt;
2248 
2249 	CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_INFRA);
2250 	CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_INFRA);
2251 	CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PASS_BCN);
2252 
2253 	/* Set probe resp timeout to infinite */
2254 	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_PROBE_RESP_TO, 0);
2255 
2256 	/*
2257 	 * TODO: factor out following part
2258 	 */
2259 
2260 	mac_status = CSR_READ_4(sc, BWI_MAC_STATUS);
2261 	mac_status &= ~(BWI_MAC_STATUS_OPMODE_HOSTAP |
2262 	    BWI_MAC_STATUS_PASS_CTL |
2263 	    BWI_MAC_STATUS_PASS_BADPLCP |
2264 	    BWI_MAC_STATUS_PASS_BADFCS |
2265 	    BWI_MAC_STATUS_PROMISC);
2266 	mac_status |= BWI_MAC_STATUS_INFRA;
2267 
2268 	/* Always turn on PROMISC on old hardware */
2269 	if (mac->mac_rev < 5)
2270 		mac_status |= BWI_MAC_STATUS_PROMISC;
2271 
2272 	switch (ic->ic_opmode) {
2273 	case IEEE80211_M_IBSS:
2274 		mac_status &= ~BWI_MAC_STATUS_INFRA;
2275 		break;
2276 	case IEEE80211_M_HOSTAP:
2277 		mac_status |= BWI_MAC_STATUS_OPMODE_HOSTAP;
2278 		break;
2279 	case IEEE80211_M_MONITOR:
2280 #if 0
2281 		/* Do you want data from your microwave oven? */
2282 		mac_status |= BWI_MAC_STATUS_PASS_CTL |
2283 			      BWI_MAC_STATUS_PASS_BADPLCP |
2284 			      BWI_MAC_STATUS_PASS_BADFCS;
2285 #else
2286 		mac_status |= BWI_MAC_STATUS_PASS_CTL;
2287 #endif
2288 		/* Promisc? */
2289 		break;
2290 	default:
2291 		break;
2292 	}
2293 
2294 	if (sc->sc_if.if_flags & IFF_PROMISC)
2295 		mac_status |= BWI_MAC_STATUS_PROMISC;
2296 
2297 	CSR_WRITE_4(sc, BWI_MAC_STATUS, mac_status);
2298 
2299 	if (ic->ic_opmode != IEEE80211_M_IBSS &&
2300 	    ic->ic_opmode != IEEE80211_M_HOSTAP) {
2301 		if (sc->sc_bbp_id == BWI_BBPID_BCM4306 && sc->sc_bbp_rev == 3)
2302 			pre_tbtt = 100;
2303 		else
2304 			pre_tbtt = 50;
2305 	} else
2306 		pre_tbtt = 2;
2307 	CSR_WRITE_2(sc, BWI_MAC_PRE_TBTT, pre_tbtt);
2308 }
2309 
2310 static void
2311 bwi_mac_hostflags_init(struct bwi_mac *mac)
2312 {
2313 	struct bwi_softc *sc = mac->mac_sc;
2314 	struct bwi_phy *phy = &mac->mac_phy;
2315 	struct bwi_rf *rf = &mac->mac_rf;
2316 	uint64_t host_flags;
2317 
2318 	if (phy->phy_mode == IEEE80211_MODE_11A)
2319 		return;
2320 
2321 	host_flags = HFLAGS_READ(mac);
2322 	host_flags |= BWI_HFLAG_SYM_WA;
2323 
2324 	if (phy->phy_mode == IEEE80211_MODE_11G) {
2325 		if (phy->phy_rev == 1)
2326 			host_flags |= BWI_HFLAG_GDC_WA;
2327 		if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9)
2328 			host_flags |= BWI_HFLAG_OFDM_PA;
2329 	} else if (phy->phy_mode == IEEE80211_MODE_11B) {
2330 		if (phy->phy_rev >= 2 && rf->rf_type == BWI_RF_T_BCM2050)
2331 			host_flags &= ~BWI_HFLAG_GDC_WA;
2332 	} else {
2333 		panic("unknown PHY mode %u\n", phy->phy_mode);
2334 	}
2335 
2336 	HFLAGS_WRITE(mac, host_flags);
2337 }
2338 
2339 static void
2340 bwi_mac_bss_param_init(struct bwi_mac *mac)
2341 {
2342 	struct bwi_softc *sc = mac->mac_sc;
2343 	struct bwi_phy *phy = &mac->mac_phy;
2344 	struct bwi_retry_lim lim;
2345 	uint16_t cw_min;
2346 
2347 	/*
2348 	 * Set short/long retry limits
2349 	 */
2350 	memset(&lim, 0, sizeof(lim));
2351 	lim.shretry = BWI_SHRETRY;
2352 	lim.shretry_fb = BWI_SHRETRY_FB;
2353 	lim.lgretry = BWI_LGRETRY;
2354 	lim.lgretry_fb = BWI_LGRETRY_FB;
2355 	bwi_mac_set_retry_lim(mac, &lim);
2356 
2357 	/*
2358 	 * Implicitly prevent firmware from sending probe response
2359 	 * by setting its "probe response timeout" to 1us.
2360 	 */
2361 	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_PROBE_RESP_TO, 1);
2362 
2363 	/*
2364 	 * XXX MAC level acknowledge and CW min/max should depend
2365 	 * on the char rateset of the IBSS/BSS to join.
2366 	 */
2367 
2368 	/*
2369 	 * Set MAC level acknowledge rates
2370 	 */
2371 	bwi_mac_set_ackrates(mac, &sc->sc_ic.ic_sup_rates[phy->phy_mode]);
2372 
2373 	/*
2374 	 * Set CW min
2375 	 */
2376 	if (phy->phy_mode == IEEE80211_MODE_11B)
2377 		cw_min = IEEE80211_CW_MIN_0;
2378 	else
2379 		cw_min = IEEE80211_CW_MIN_1;
2380 	MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_CWMIN, cw_min);
2381 
2382 	/*
2383 	 * Set CW max
2384 	 */
2385 	MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_CWMAX,
2386 	    IEEE80211_CW_MAX);
2387 }
2388 
2389 static void
2390 bwi_mac_set_retry_lim(struct bwi_mac *mac, const struct bwi_retry_lim *lim)
2391 {
2392 	/* Short/Long retry limit */
2393 	MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_SHRETRY,
2394 	    lim->shretry);
2395 	MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_LGRETRY,
2396 	    lim->lgretry);
2397 
2398 	/* Short/Long retry fallback limit */
2399 	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_SHRETRY_FB,
2400 	    lim->shretry_fb);
2401 	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_LGRETEY_FB,
2402 	    lim->lgretry_fb);
2403 }
2404 
2405 static void
2406 bwi_mac_set_ackrates(struct bwi_mac *mac, const struct ieee80211_rateset *rs)
2407 {
2408 	int i;
2409 
2410 	/* XXX not standard conforming */
2411 	for (i = 0; i < rs->rs_nrates; ++i) {
2412 		enum bwi_ieee80211_modtype modtype;
2413 		uint16_t ofs;
2414 
2415 		modtype = bwi_ieee80211_rate2modtype(rs->rs_rates[i]);
2416 		switch (modtype) {
2417 		case IEEE80211_MODTYPE_DS:
2418 			ofs = 0x4c0;
2419 			ofs += (bwi_ieee80211_rate2plcp(rs->rs_rates[i],
2420 			    IEEE80211_MODE_11B) & 0xf) * 2;
2421 			break;
2422 		case IEEE80211_MODTYPE_OFDM:
2423 			ofs = 0x480;
2424 			ofs += (bwi_ieee80211_rate2plcp(rs->rs_rates[i],
2425 			    IEEE80211_MODE_11G) & 0xf) * 2;
2426 			break;
2427 		default:
2428 			panic("unsupported modtype %u\n", modtype);
2429 		}
2430 
2431 		MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, ofs + 0x20,
2432 		    MOBJ_READ_2(mac, BWI_COMM_MOBJ, ofs));
2433 	}
2434 }
2435 
2436 static int
2437 bwi_mac_start(struct bwi_mac *mac)
2438 {
2439 	struct bwi_softc *sc = mac->mac_sc;
2440 
2441 	CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_ENABLE);
2442 	CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_INTR_READY);
2443 
2444 	/* Flush pending bus writes */
2445 	CSR_READ_4(sc, BWI_MAC_STATUS);
2446 	CSR_READ_4(sc, BWI_MAC_INTR_STATUS);
2447 
2448 	return (bwi_mac_config_ps(mac));
2449 }
2450 
2451 static int
2452 bwi_mac_stop(struct bwi_mac *mac)
2453 {
2454 	struct bwi_softc *sc = mac->mac_sc;
2455 	int error, i;
2456 
2457 	error = bwi_mac_config_ps(mac);
2458 	if (error)
2459 		return (error);
2460 
2461 	CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_ENABLE);
2462 
2463 	/* Flush pending bus write */
2464 	CSR_READ_4(sc, BWI_MAC_STATUS);
2465 
2466 #define NRETRY	10000
2467 	for (i = 0; i < NRETRY; ++i) {
2468 		if (CSR_READ_4(sc, BWI_MAC_INTR_STATUS) & BWI_INTR_READY)
2469 			break;
2470 		DELAY(1);
2471 	}
2472 	if (i == NRETRY) {
2473 		aprint_error_dev(sc->sc_dev, "can't stop MAC\n");
2474 		return (ETIMEDOUT);
2475 	}
2476 #undef NRETRY
2477 
2478 	return (0);
2479 }
2480 
2481 static int
2482 bwi_mac_config_ps(struct bwi_mac *mac)
2483 {
2484 	struct bwi_softc *sc = mac->mac_sc;
2485 	uint32_t status;
2486 
2487 	status = CSR_READ_4(sc, BWI_MAC_STATUS);
2488 
2489 	status &= ~BWI_MAC_STATUS_HW_PS;
2490 	status |= BWI_MAC_STATUS_WAKEUP;
2491 	CSR_WRITE_4(sc, BWI_MAC_STATUS, status);
2492 
2493 	/* Flush pending bus write */
2494 	CSR_READ_4(sc, BWI_MAC_STATUS);
2495 
2496 	if (mac->mac_rev >= 5) {
2497 		int i;
2498 
2499 #define NRETRY	100
2500 		for (i = 0; i < NRETRY; ++i) {
2501 			if (MOBJ_READ_2(mac, BWI_COMM_MOBJ,
2502 			    BWI_COMM_MOBJ_UCODE_STATE) != BWI_UCODE_STATE_PS)
2503 				break;
2504 			DELAY(10);
2505 		}
2506 		if (i == NRETRY) {
2507 			aprint_error_dev(sc->sc_dev, "config PS failed\n");
2508 			return (ETIMEDOUT);
2509 		}
2510 #undef NRETRY
2511 	}
2512 	return (0);
2513 }
2514 
2515 static void
2516 bwi_mac_reset_hwkeys(struct bwi_mac *mac)
2517 {
2518 	/* TODO: firmware crypto */
2519 	MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_KEYTABLE_OFS);
2520 }
2521 
2522 static void
2523 bwi_mac_shutdown(struct bwi_mac *mac)
2524 {
2525 	struct bwi_softc *sc = mac->mac_sc;
2526 	int i;
2527 
2528 	if (mac->mac_flags & BWI_MAC_F_HAS_TXSTATS)
2529 		(sc->sc_free_txstats)(sc);
2530 
2531 	(sc->sc_free_rx_ring)(sc);
2532 
2533 	for (i = 0; i < BWI_TX_NRING; ++i)
2534 		(sc->sc_free_tx_ring)(sc, i);
2535 
2536 	bwi_rf_off(mac);
2537 
2538 	/* TODO: LED */
2539 
2540 	bwi_mac_gpio_fini(mac);
2541 
2542 	bwi_rf_off(mac); /* XXX again */
2543 	CSR_WRITE_2(sc, BWI_BBP_ATTEN, BWI_BBP_ATTEN_MAGIC);
2544 	bwi_regwin_disable(sc, &mac->mac_regwin, 0);
2545 
2546 	mac->mac_flags &= ~BWI_MAC_F_INITED;
2547 }
2548 
2549 static int
2550 bwi_mac_get_property(struct bwi_mac *mac)
2551 {
2552 	struct bwi_softc *sc = mac->mac_sc;
2553 	enum bwi_bus_space old_bus_space;
2554 	uint32_t val;
2555 
2556 	/*
2557 	 * Byte swap
2558 	 */
2559 	val = CSR_READ_4(sc, BWI_MAC_STATUS);
2560 	if (val & BWI_MAC_STATUS_BSWAP) {
2561 		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "need byte swap\n");
2562 		mac->mac_flags |= BWI_MAC_F_BSWAP;
2563 	}
2564 
2565 	/*
2566 	 * DMA address space
2567 	 */
2568 	old_bus_space = sc->sc_bus_space;
2569 
2570 	val = CSR_READ_4(sc, BWI_STATE_HI);
2571 	if (__SHIFTOUT(val, BWI_STATE_HI_FLAGS_MASK) &
2572 	    BWI_STATE_HI_FLAG_64BIT) {
2573 		/* 64bit address */
2574 		sc->sc_bus_space = BWI_BUS_SPACE_64BIT;
2575 		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "64bit bus space\n");
2576 	} else {
2577 		uint32_t txrx_reg = BWI_TXRX_CTRL_BASE + BWI_TX32_CTRL;
2578 
2579 		CSR_WRITE_4(sc, txrx_reg, BWI_TXRX32_CTRL_ADDRHI_MASK);
2580 		if (CSR_READ_4(sc, txrx_reg) & BWI_TXRX32_CTRL_ADDRHI_MASK) {
2581 			/* 32bit address */
2582 			sc->sc_bus_space = BWI_BUS_SPACE_32BIT;
2583 			DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH,
2584 			    "32bit bus space\n");
2585 		} else {
2586 			/* 30bit address */
2587 			sc->sc_bus_space = BWI_BUS_SPACE_30BIT;
2588 			DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH,
2589 			    "30bit bus space\n");
2590 		}
2591 	}
2592 
2593 	if (old_bus_space != 0 && old_bus_space != sc->sc_bus_space) {
2594 		aprint_error_dev(sc->sc_dev, "MACs bus space mismatch!\n");
2595 		return (ENXIO);
2596 	}
2597 
2598 	return (0);
2599 }
2600 
2601 static void
2602 bwi_mac_updateslot(struct bwi_mac *mac, int shslot)
2603 {
2604 	uint16_t slot_time;
2605 
2606 	if (mac->mac_phy.phy_mode == IEEE80211_MODE_11B)
2607 		return;
2608 
2609 	if (shslot)
2610 		slot_time = IEEE80211_DUR_SHSLOT;
2611 	else
2612 		slot_time = IEEE80211_DUR_SLOT;
2613 
2614 	CSR_WRITE_2(mac->mac_sc, BWI_MAC_SLOTTIME,
2615 	    slot_time + BWI_MAC_SLOTTIME_ADJUST);
2616 	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_SLOTTIME, slot_time);
2617 }
2618 
2619 static int
2620 bwi_mac_attach(struct bwi_softc *sc, int id, uint8_t rev)
2621 {
2622 	struct bwi_mac *mac;
2623 	int i;
2624 
2625 	KASSERT(sc->sc_nmac <= BWI_MAC_MAX && sc->sc_nmac >= 0);
2626 
2627 	if (sc->sc_nmac == BWI_MAC_MAX) {
2628 		aprint_error_dev(sc->sc_dev, "too many MACs\n");
2629 		return (0);
2630 	}
2631 
2632 	/*
2633 	 * More than one MAC is only supported by BCM4309
2634 	 */
2635 	if (sc->sc_nmac != 0 &&
2636 	    sc->sc_pci_did != PCI_PRODUCT_BROADCOM_BCM4309) {
2637 		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH,
2638 		    "ignore %dth MAC\n", sc->sc_nmac);
2639 		return (0);
2640 	}
2641 
2642 	mac = &sc->sc_mac[sc->sc_nmac];
2643 
2644 	/* XXX will this happen? */
2645 	if (BWI_REGWIN_EXIST(&mac->mac_regwin)) {
2646 		aprint_error_dev(sc->sc_dev, "%dth MAC already attached\n",
2647 		    sc->sc_nmac);
2648 		return (0);
2649 	}
2650 
2651 	/*
2652 	 * Test whether the revision of this MAC is supported
2653 	 */
2654 	for (i = 0; i < __arraycount(bwi_sup_macrev); ++i) {
2655 		if (bwi_sup_macrev[i] == rev)
2656 			break;
2657 	}
2658 	if (i == __arraycount(bwi_sup_macrev)) {
2659 		aprint_error_dev(sc->sc_dev, "MAC rev %u is not supported\n",
2660 		    rev);
2661 		return (ENXIO);
2662 	}
2663 
2664 	BWI_CREATE_MAC(mac, sc, id, rev);
2665 	sc->sc_nmac++;
2666 
2667 	if (mac->mac_rev < 5) {
2668 		mac->mac_flags |= BWI_MAC_F_HAS_TXSTATS;
2669 		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "has TX stats\n");
2670 	} else {
2671 		mac->mac_flags |= BWI_MAC_F_PHYE_RESET;
2672 	}
2673 
2674 	aprint_normal_dev(sc->sc_dev, "MAC: rev %u\n", rev);
2675 	return (0);
2676 }
2677 
2678 static void
2679 bwi_mac_balance_atten(int *bbp_atten0, int *rf_atten0)
2680 {
2681 	int bbp_atten, rf_atten, rf_atten_lim = -1;
2682 
2683 	bbp_atten = *bbp_atten0;
2684 	rf_atten = *rf_atten0;
2685 
2686 	/*
2687 	 * RF attenuation affects TX power BWI_RF_ATTEN_FACTOR times
2688 	 * as much as BBP attenuation, so we try our best to keep RF
2689 	 * attenuation within range.  BBP attenuation will be clamped
2690 	 * later if it is out of range during balancing.
2691 	 *
2692 	 * BWI_RF_ATTEN_MAX0 is used as RF attenuation upper limit.
2693 	 */
2694 
2695 	/*
2696 	 * Use BBP attenuation to balance RF attenuation
2697 	 */
2698 	if (rf_atten < 0)
2699 		rf_atten_lim = 0;
2700 	else if (rf_atten > BWI_RF_ATTEN_MAX0)
2701 		rf_atten_lim = BWI_RF_ATTEN_MAX0;
2702 
2703 	if (rf_atten_lim >= 0) {
2704 		bbp_atten += (BWI_RF_ATTEN_FACTOR * (rf_atten - rf_atten_lim));
2705 		rf_atten = rf_atten_lim;
2706 	}
2707 
2708 	/*
2709 	 * If possible, use RF attenuation to balance BBP attenuation
2710 	 * NOTE: RF attenuation is still kept within range.
2711 	 */
2712 	while (rf_atten < BWI_RF_ATTEN_MAX0 && bbp_atten > BWI_BBP_ATTEN_MAX) {
2713 		bbp_atten -= BWI_RF_ATTEN_FACTOR;
2714 		++rf_atten;
2715 	}
2716 	while (rf_atten > 0 && bbp_atten < 0) {
2717 		bbp_atten += BWI_RF_ATTEN_FACTOR;
2718 		--rf_atten;
2719 	}
2720 
2721 	/* RF attenuation MUST be within range */
2722 	KASSERT(rf_atten >= 0 && rf_atten <= BWI_RF_ATTEN_MAX0);
2723 
2724 	/*
2725 	 * Clamp BBP attenuation
2726 	 */
2727 	if (bbp_atten < 0)
2728 		bbp_atten = 0;
2729 	else if (bbp_atten > BWI_BBP_ATTEN_MAX)
2730 		bbp_atten = BWI_BBP_ATTEN_MAX;
2731 
2732 	*rf_atten0 = rf_atten;
2733 	*bbp_atten0 = bbp_atten;
2734 }
2735 
2736 static void
2737 bwi_mac_adjust_tpctl(struct bwi_mac *mac, int rf_atten_adj, int bbp_atten_adj)
2738 {
2739 	struct bwi_softc *sc = mac->mac_sc;
2740 	struct bwi_rf *rf = &mac->mac_rf;
2741 	struct bwi_tpctl tpctl;
2742 	int bbp_atten, rf_atten, tp_ctrl1;
2743 
2744 	memcpy(&tpctl, &mac->mac_tpctl, sizeof(tpctl));
2745 
2746 	/* NOTE: Use signed value to do calulation */
2747 	bbp_atten = tpctl.bbp_atten;
2748 	rf_atten = tpctl.rf_atten;
2749 	tp_ctrl1 = tpctl.tp_ctrl1;
2750 
2751 	bbp_atten += bbp_atten_adj;
2752 	rf_atten += rf_atten_adj;
2753 
2754 	bwi_mac_balance_atten(&bbp_atten, &rf_atten);
2755 
2756 	if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev == 2) {
2757 		if (rf_atten <= 1) {
2758 			if (tp_ctrl1 == 0) {
2759 				tp_ctrl1 = 3;
2760 				bbp_atten += 2;
2761 				rf_atten += 2;
2762 			} else if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) {
2763 				bbp_atten +=
2764 				(BWI_RF_ATTEN_FACTOR * (rf_atten - 2));
2765 				rf_atten = 2;
2766 			}
2767 		} else if (rf_atten > 4 && tp_ctrl1 != 0) {
2768 			tp_ctrl1 = 0;
2769 			if (bbp_atten < 3) {
2770 				bbp_atten += 2;
2771 				rf_atten -= 3;
2772 			} else {
2773 				bbp_atten -= 2;
2774 				rf_atten -= 2;
2775 			}
2776 		}
2777 		bwi_mac_balance_atten(&bbp_atten, &rf_atten);
2778 	}
2779 
2780 	tpctl.bbp_atten = bbp_atten;
2781 	tpctl.rf_atten = rf_atten;
2782 	tpctl.tp_ctrl1 = tp_ctrl1;
2783 
2784 	bwi_mac_lock(mac);
2785 	bwi_mac_set_tpctl_11bg(mac, &tpctl);
2786 	bwi_mac_unlock(mac);
2787 }
2788 
2789 /*
2790  * http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower
2791  */
2792 static void
2793 bwi_mac_calibrate_txpower(struct bwi_mac *mac, enum bwi_txpwrcb_type type)
2794 {
2795 	struct bwi_softc *sc = mac->mac_sc;
2796 	struct bwi_rf *rf = &mac->mac_rf;
2797 	int8_t tssi[4], tssi_avg, cur_txpwr;
2798 	int error, i, ofdm_tssi;
2799 	int txpwr_diff, rf_atten_adj, bbp_atten_adj;
2800 
2801 	if (!sc->sc_txpwr_calib)
2802 		return;
2803 
2804 	if (mac->mac_flags & BWI_MAC_F_TPCTL_ERROR) {
2805 		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER,
2806 		    "tpctl error happened, can't set txpower\n");
2807 		return;
2808 	}
2809 
2810 	if (BWI_IS_BRCM_BU4306(sc)) {
2811 		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER,
2812 		    "BU4306, can't set txpower\n");
2813 		return;
2814 	}
2815 
2816 	/*
2817 	 * Save latest TSSI and reset the related memory objects
2818 	 */
2819 	ofdm_tssi = 0;
2820 	error = bwi_rf_get_latest_tssi(mac, tssi, BWI_COMM_MOBJ_TSSI_DS);
2821 	if (error) {
2822 		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "no DS tssi\n");
2823 
2824 		if (mac->mac_phy.phy_mode == IEEE80211_MODE_11B) {
2825 			if (type == BWI_TXPWR_FORCE) {
2826 				rf_atten_adj = 0;
2827 				bbp_atten_adj = 1;
2828 				goto calib;
2829 			} else {
2830 				return;
2831 			}
2832 		}
2833 
2834 		error = bwi_rf_get_latest_tssi(mac, tssi,
2835 		    BWI_COMM_MOBJ_TSSI_OFDM);
2836 		if (error) {
2837 			DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER,
2838 			    "no OFDM tssi\n");
2839 			if (type == BWI_TXPWR_FORCE) {
2840 				rf_atten_adj = 0;
2841 				bbp_atten_adj = 1;
2842 				goto calib;
2843 			} else {
2844 				return;
2845 			}
2846 		}
2847 
2848 		for (i = 0; i < 4; ++i) {
2849 			tssi[i] += 0x20;
2850 			tssi[i] &= 0x3f;
2851 		}
2852 		ofdm_tssi = 1;
2853 	}
2854 	bwi_rf_clear_tssi(mac);
2855 
2856 	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER,
2857 	    "tssi0 %d, tssi1 %d, tssi2 %d, tssi3 %d\n",
2858 	    tssi[0], tssi[1], tssi[2], tssi[3]);
2859 
2860 	/*
2861 	 * Calculate RF/BBP attenuation adjustment based on
2862 	 * the difference between desired TX power and sampled
2863 	 * TX power.
2864 	 */
2865 	/* +8 == "each incremented by 1/2" */
2866 	tssi_avg = (tssi[0] + tssi[1] + tssi[2] + tssi[3] + 8) / 4;
2867 	if (ofdm_tssi && (HFLAGS_READ(mac) & BWI_HFLAG_PWR_BOOST_DS))
2868 		tssi_avg -= 13;
2869 
2870 	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "tssi avg %d\n", tssi_avg);
2871 
2872 	error = bwi_rf_tssi2dbm(mac, tssi_avg, &cur_txpwr);
2873 	if (error)
2874 		return;
2875 	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "current txpower %d\n",
2876 	    cur_txpwr);
2877 
2878 	txpwr_diff = rf->rf_txpower_max - cur_txpwr; /* XXX ni_txpower */
2879 
2880 	rf_atten_adj = -howmany(txpwr_diff, 8);
2881 
2882 	if (type == BWI_TXPWR_INIT) {
2883 		/*
2884 		 * Move toward EEPROM max TX power as fast as we can
2885 		 */
2886 		bbp_atten_adj = -txpwr_diff;
2887 	} else {
2888 		bbp_atten_adj = -(txpwr_diff / 2);
2889 	}
2890 	bbp_atten_adj -= (BWI_RF_ATTEN_FACTOR * rf_atten_adj);
2891 
2892 	if (rf_atten_adj == 0 && bbp_atten_adj == 0) {
2893 		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER, "%s\n",
2894 		    "no need to adjust RF/BBP attenuation");
2895 		/* TODO: LO */
2896 		return;
2897 	}
2898 
2899 calib:
2900 	DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_TXPOWER,
2901 	    "rf atten adjust %d, bbp atten adjust %d\n",
2902 	    rf_atten_adj, bbp_atten_adj);
2903 	bwi_mac_adjust_tpctl(mac, rf_atten_adj, bbp_atten_adj);
2904 	/* TODO: LO */
2905 }
2906 
2907 static void
2908 bwi_mac_lock(struct bwi_mac *mac)
2909 {
2910 	struct bwi_softc *sc = mac->mac_sc;
2911 	struct ieee80211com *ic = &sc->sc_ic;
2912 
2913 	KASSERT((mac->mac_flags & BWI_MAC_F_LOCKED) == 0);
2914 
2915 	if (mac->mac_rev < 3)
2916 		bwi_mac_stop(mac);
2917 	else if (ic->ic_opmode != IEEE80211_M_HOSTAP)
2918 		bwi_mac_config_ps(mac);
2919 
2920 	CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_RFLOCK);
2921 
2922 	/* Flush pending bus write */
2923 	CSR_READ_4(sc, BWI_MAC_STATUS);
2924 	DELAY(10);
2925 
2926 	mac->mac_flags |= BWI_MAC_F_LOCKED;
2927 }
2928 
2929 static void
2930 bwi_mac_unlock(struct bwi_mac *mac)
2931 {
2932 	struct bwi_softc *sc = mac->mac_sc;
2933 	struct ieee80211com *ic = &sc->sc_ic;
2934 
2935 	KASSERT(mac->mac_flags & BWI_MAC_F_LOCKED);
2936 
2937 	CSR_READ_2(sc, BWI_PHYINFO); /* dummy read */
2938 
2939 	CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_RFLOCK);
2940 
2941 	if (mac->mac_rev < 3)
2942 		bwi_mac_start(mac);
2943 	else if (ic->ic_opmode != IEEE80211_M_HOSTAP)
2944 		bwi_mac_config_ps(mac);
2945 
2946 	mac->mac_flags &= ~BWI_MAC_F_LOCKED;
2947 }
2948 
2949 static void
2950 bwi_mac_set_promisc(struct bwi_mac *mac, int promisc)
2951 {
2952 	struct bwi_softc *sc = mac->mac_sc;
2953 
2954 	if (mac->mac_rev < 5) /* Promisc is always on */
2955 		return;
2956 
2957 	if (promisc)
2958 		CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PROMISC);
2959 	else
2960 		CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PROMISC);
2961 }
2962 
2963 /* PHY */
2964 
2965 static void
2966 bwi_phy_write(struct bwi_mac *mac, uint16_t ctrl, uint16_t data)
2967 {
2968 	struct bwi_softc *sc = mac->mac_sc;
2969 
2970 	/* TODO: 11A */
2971 	CSR_WRITE_2(sc, BWI_PHY_CTRL, ctrl);
2972 	CSR_WRITE_2(sc, BWI_PHY_DATA, data);
2973 }
2974 
2975 static uint16_t
2976 bwi_phy_read(struct bwi_mac *mac, uint16_t ctrl)
2977 {
2978 	struct bwi_softc *sc = mac->mac_sc;
2979 
2980 	/* TODO: 11A */
2981 	CSR_WRITE_2(sc, BWI_PHY_CTRL, ctrl);
2982 	return (CSR_READ_2(sc, BWI_PHY_DATA));
2983 }
2984 
2985 static int
2986 bwi_phy_attach(struct bwi_mac *mac)
2987 {
2988 	struct bwi_softc *sc = mac->mac_sc;
2989 	struct bwi_phy *phy = &mac->mac_phy;
2990 	uint8_t phyrev, phytype, phyver;
2991 	uint16_t val;
2992 	int i;
2993 
2994 	/* Get PHY type/revision/version */
2995 	val = CSR_READ_2(sc, BWI_PHYINFO);
2996 	phyrev = __SHIFTOUT(val, BWI_PHYINFO_REV_MASK);
2997 	phytype = __SHIFTOUT(val, BWI_PHYINFO_TYPE_MASK);
2998 	phyver = __SHIFTOUT(val, BWI_PHYINFO_VER_MASK);
2999 	aprint_normal_dev(sc->sc_dev, "PHY type %d, rev %d, ver %d\n",
3000 	    phytype, phyrev, phyver);
3001 
3002 	/*
3003 	 * Verify whether the revision of the PHY type is supported
3004 	 * Convert PHY type to ieee80211_phymode
3005 	 */
3006 	switch (phytype) {
3007 	case BWI_PHYINFO_TYPE_11A:
3008 		if (phyrev >= 4) {
3009 			aprint_error_dev(sc->sc_dev,
3010 			    "unsupported 11A PHY, rev %u\n",
3011 			    phyrev);
3012 			return (ENXIO);
3013 		}
3014 		phy->phy_init = bwi_phy_init_11a;
3015 		phy->phy_mode = IEEE80211_MODE_11A;
3016 		phy->phy_tbl_ctrl = BWI_PHYR_TBL_CTRL_11A;
3017 		phy->phy_tbl_data_lo = BWI_PHYR_TBL_DATA_LO_11A;
3018 		phy->phy_tbl_data_hi = BWI_PHYR_TBL_DATA_HI_11A;
3019 		break;
3020 	case BWI_PHYINFO_TYPE_11B:
3021 		for (i = 0; i < __arraycount(bwi_sup_bphy); ++i) {
3022 			if (phyrev == bwi_sup_bphy[i].rev) {
3023 				phy->phy_init = bwi_sup_bphy[i].init;
3024 				break;
3025 			}
3026 		}
3027 		if (i == __arraycount(bwi_sup_bphy)) {
3028 			aprint_error_dev(sc->sc_dev,
3029 			    "unsupported 11B PHY, rev %u\n",
3030 			    phyrev);
3031 			return (ENXIO);
3032 		}
3033 		phy->phy_mode = IEEE80211_MODE_11B;
3034 		break;
3035 	case BWI_PHYINFO_TYPE_11G:
3036 		if (phyrev > 8) {
3037 			aprint_error_dev(sc->sc_dev,
3038 			    "unsupported 11G PHY, rev %u\n",
3039 			    phyrev);
3040 			return (ENXIO);
3041 		}
3042 		phy->phy_init = bwi_phy_init_11g;
3043 		phy->phy_mode = IEEE80211_MODE_11G;
3044 		phy->phy_tbl_ctrl = BWI_PHYR_TBL_CTRL_11G;
3045 		phy->phy_tbl_data_lo = BWI_PHYR_TBL_DATA_LO_11G;
3046 		phy->phy_tbl_data_hi = BWI_PHYR_TBL_DATA_HI_11G;
3047 		break;
3048 	default:
3049 		aprint_error_dev(sc->sc_dev, "unsupported PHY type %d\n",
3050 		    phytype);
3051 		return (ENXIO);
3052 	}
3053 	phy->phy_rev = phyrev;
3054 	phy->phy_version = phyver;
3055 
3056 	return (0);
3057 }
3058 
3059 static void
3060 bwi_phy_set_bbp_atten(struct bwi_mac *mac, uint16_t bbp_atten)
3061 {
3062 	struct bwi_phy *phy = &mac->mac_phy;
3063 	uint16_t mask = 0x000f;
3064 
3065 	if (phy->phy_version == 0) {
3066 		CSR_FILT_SETBITS_2(mac->mac_sc, BWI_BBP_ATTEN, ~mask,
3067 		    __SHIFTIN(bbp_atten, mask));
3068 	} else {
3069 		if (phy->phy_version > 1)
3070 			mask <<= 2;
3071 		else
3072 			mask <<= 3;
3073 		PHY_FILT_SETBITS(mac, BWI_PHYR_BBP_ATTEN, ~mask,
3074 		    __SHIFTIN(bbp_atten, mask));
3075 	}
3076 }
3077 
3078 static int
3079 bwi_phy_calibrate(struct bwi_mac *mac)
3080 {
3081 	struct bwi_phy *phy = &mac->mac_phy;
3082 
3083 	/* Dummy read */
3084 	CSR_READ_4(mac->mac_sc, BWI_MAC_STATUS);
3085 
3086 	/* Don't re-init */
3087 	if (phy->phy_flags & BWI_PHY_F_CALIBRATED)
3088 		return (0);
3089 
3090 	if (phy->phy_mode == IEEE80211_MODE_11G && phy->phy_rev == 1) {
3091 		bwi_mac_reset(mac, 0);
3092 		bwi_phy_init_11g(mac);
3093 		bwi_mac_reset(mac, 1);
3094 	}
3095 
3096 	phy->phy_flags |= BWI_PHY_F_CALIBRATED;
3097 
3098 	return (0);
3099 }
3100 
3101 static void
3102 bwi_tbl_write_2(struct bwi_mac *mac, uint16_t ofs, uint16_t data)
3103 {
3104 	struct bwi_phy *phy = &mac->mac_phy;
3105 
3106 	KASSERT(phy->phy_tbl_ctrl != 0 && phy->phy_tbl_data_lo != 0);
3107 	PHY_WRITE(mac, phy->phy_tbl_ctrl, ofs);
3108 	PHY_WRITE(mac, phy->phy_tbl_data_lo, data);
3109 }
3110 
3111 static void
3112 bwi_tbl_write_4(struct bwi_mac *mac, uint16_t ofs, uint32_t data)
3113 {
3114 	struct bwi_phy *phy = &mac->mac_phy;
3115 
3116 	KASSERT(phy->phy_tbl_data_lo != 0 && phy->phy_tbl_data_hi != 0 &&
3117 	    phy->phy_tbl_ctrl != 0);
3118 
3119 	PHY_WRITE(mac, phy->phy_tbl_ctrl, ofs);
3120 	PHY_WRITE(mac, phy->phy_tbl_data_hi, data >> 16);
3121 	PHY_WRITE(mac, phy->phy_tbl_data_lo, data & 0xffff);
3122 }
3123 
3124 static void
3125 bwi_nrssi_write(struct bwi_mac *mac, uint16_t ofs, int16_t data)
3126 {
3127 	PHY_WRITE(mac, BWI_PHYR_NRSSI_CTRL, ofs);
3128 	PHY_WRITE(mac, BWI_PHYR_NRSSI_DATA, (uint16_t)data);
3129 }
3130 
3131 static int16_t
3132 bwi_nrssi_read(struct bwi_mac *mac, uint16_t ofs)
3133 {
3134 	PHY_WRITE(mac, BWI_PHYR_NRSSI_CTRL, ofs);
3135 	return ((int16_t)PHY_READ(mac, BWI_PHYR_NRSSI_DATA));
3136 }
3137 
3138 static void
3139 bwi_phy_init_11a(struct bwi_mac *mac)
3140 {
3141 	/* TODO: 11A */
3142 }
3143 
3144 static void
3145 bwi_phy_init_11g(struct bwi_mac *mac)
3146 {
3147 	struct bwi_softc *sc = mac->mac_sc;
3148 	struct bwi_phy *phy = &mac->mac_phy;
3149 	struct bwi_rf *rf = &mac->mac_rf;
3150 	const struct bwi_tpctl *tpctl = &mac->mac_tpctl;
3151 
3152 	if (phy->phy_rev == 1)
3153 		bwi_phy_init_11b_rev5(mac);
3154 	else
3155 		bwi_phy_init_11b_rev6(mac);
3156 
3157 	if (phy->phy_rev >= 2 || (phy->phy_flags & BWI_PHY_F_LINKED))
3158 		bwi_phy_config_11g(mac);
3159 
3160 	if (phy->phy_rev >= 2) {
3161 		PHY_WRITE(mac, 0x814, 0);
3162 		PHY_WRITE(mac, 0x815, 0);
3163 
3164 		if (phy->phy_rev == 2) {
3165 			PHY_WRITE(mac, 0x811, 0);
3166 			PHY_WRITE(mac, 0x15, 0xc0);
3167 		} else if (phy->phy_rev > 5) {
3168 			PHY_WRITE(mac, 0x811, 0x400);
3169 			PHY_WRITE(mac, 0x15, 0xc0);
3170 		}
3171 	}
3172 
3173 	if (phy->phy_rev >= 2 || (phy->phy_flags & BWI_PHY_F_LINKED)) {
3174 		uint16_t val;
3175 
3176 		val = PHY_READ(mac, 0x400) & 0xff;
3177 		if (val == 3 || val == 5) {
3178 			PHY_WRITE(mac, 0x4c2, 0x1816);
3179 			PHY_WRITE(mac, 0x4c3, 0x8006);
3180 			if (val == 5) {
3181 				PHY_FILT_SETBITS(mac, 0x4cc,
3182 						 0xff, 0x1f00);
3183 			}
3184 		}
3185 	}
3186 
3187 	if ((phy->phy_rev <= 2 && (phy->phy_flags & BWI_PHY_F_LINKED)) ||
3188 	    phy->phy_rev >= 2)
3189 		PHY_WRITE(mac, 0x47e, 0x78);
3190 
3191 	if (rf->rf_rev == 8) {
3192 		PHY_SETBITS(mac, 0x801, 0x80);
3193 		PHY_SETBITS(mac, 0x43e, 0x4);
3194 	}
3195 
3196 	if (phy->phy_rev >= 2 && (phy->phy_flags & BWI_PHY_F_LINKED))
3197 		bwi_rf_get_gains(mac);
3198 
3199 	if (rf->rf_rev != 8)
3200 		bwi_rf_init(mac);
3201 
3202 	if (tpctl->tp_ctrl2 == 0xffff) {
3203 		bwi_rf_lo_update(mac);
3204 	} else {
3205 		if (rf->rf_type == BWI_RF_T_BCM2050 && rf->rf_rev == 8) {
3206 			RF_WRITE(mac, 0x52,
3207 			    (tpctl->tp_ctrl1 << 4) | tpctl->tp_ctrl2);
3208 		} else {
3209 			RF_FILT_SETBITS(mac, 0x52, 0xfff0, tpctl->tp_ctrl2);
3210 		}
3211 
3212 		if (phy->phy_rev >= 6) {
3213 			PHY_FILT_SETBITS(mac, 0x36, 0xfff,
3214 			    tpctl->tp_ctrl2 << 12);
3215 		}
3216 
3217 		if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9)
3218 			PHY_WRITE(mac, 0x2e, 0x8075);
3219 		else
3220 			PHY_WRITE(mac, 0x2e, 0x807f);
3221 
3222 		if (phy->phy_rev < 2)
3223 			PHY_WRITE(mac, 0x2f, 0x101);
3224 		else
3225 			PHY_WRITE(mac, 0x2f, 0x202);
3226 	}
3227 
3228 	if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
3229 		bwi_rf_lo_adjust(mac, tpctl);
3230 		PHY_WRITE(mac, 0x80f, 0x8078);
3231 	}
3232 
3233 	if ((sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) == 0) {
3234 		bwi_rf_init_hw_nrssi_table(mac, 0xffff /* XXX */);
3235 		bwi_rf_set_nrssi_thr(mac);
3236 	} else if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
3237 		if (rf->rf_nrssi[0] == BWI_INVALID_NRSSI) {
3238 			KASSERT(rf->rf_nrssi[1] == BWI_INVALID_NRSSI);
3239 			bwi_rf_calc_nrssi_slope(mac);
3240 		} else {
3241 			KASSERT(rf->rf_nrssi[1] != BWI_INVALID_NRSSI);
3242 			bwi_rf_set_nrssi_thr(mac);
3243 		}
3244 	}
3245 
3246 	if (rf->rf_rev == 8)
3247 		PHY_WRITE(mac, 0x805, 0x3230);
3248 
3249 	bwi_mac_init_tpctl_11bg(mac);
3250 
3251 	if (sc->sc_bbp_id == BWI_BBPID_BCM4306 && sc->sc_bbp_pkg == 2) {
3252 		PHY_CLRBITS(mac, 0x429, 0x4000);
3253 		PHY_CLRBITS(mac, 0x4c3, 0x8000);
3254 	}
3255 }
3256 
3257 static void
3258 bwi_phy_init_11b_rev2(struct bwi_mac *mac)
3259 {
3260 	struct bwi_softc *sc;
3261 
3262 	sc = mac->mac_sc;
3263 
3264 	/* TODO: 11B */
3265 	aprint_error_dev(sc->sc_dev, "%s is not implemented yet\n", __func__);
3266 }
3267 
3268 static void
3269 bwi_phy_init_11b_rev4(struct bwi_mac *mac)
3270 {
3271 	struct bwi_softc *sc = mac->mac_sc;
3272 	struct bwi_rf *rf = &mac->mac_rf;
3273 	uint16_t val, ofs;
3274 	uint chan;
3275 
3276 	CSR_WRITE_2(sc, BWI_BPHY_CTRL, BWI_BPHY_CTRL_INIT);
3277 
3278 	PHY_WRITE(mac, 0x20, 0x301c);
3279 	PHY_WRITE(mac, 0x26, 0);
3280 	PHY_WRITE(mac, 0x30, 0xc6);
3281 	PHY_WRITE(mac, 0x88, 0x3e00);
3282 
3283 	for (ofs = 0, val = 0x3c3d; ofs < 30; ++ofs, val -= 0x202)
3284 		PHY_WRITE(mac, 0x89 + ofs, val);
3285 
3286 	CSR_WRITE_2(sc, BWI_PHY_MAGIC_REG1, BWI_PHY_MAGIC_REG1_VAL1);
3287 
3288 	chan = rf->rf_curchan;
3289 	if (chan == IEEE80211_CHAN_ANY)
3290 		chan = 6;	/* Force to channel 6 */
3291 	bwi_rf_set_chan(mac, chan, 0);
3292 
3293 	if (rf->rf_type != BWI_RF_T_BCM2050) {
3294 		RF_WRITE(mac, 0x75, 0x80);
3295 		RF_WRITE(mac, 0x79, 0x81);
3296 	}
3297 
3298 	RF_WRITE(mac, 0x50, 0x20);
3299 	RF_WRITE(mac, 0x50, 0x23);
3300 
3301 	if (rf->rf_type == BWI_RF_T_BCM2050) {
3302 		RF_WRITE(mac, 0x50, 0x20);
3303 		RF_WRITE(mac, 0x5a, 0x70);
3304 		RF_WRITE(mac, 0x5b, 0x7b);
3305 		RF_WRITE(mac, 0x5c, 0xb0);
3306 		RF_WRITE(mac, 0x7a, 0xf);
3307 		PHY_WRITE(mac, 0x38, 0x677);
3308 		bwi_rf_init_bcm2050(mac);
3309 	}
3310 
3311 	PHY_WRITE(mac, 0x14, 0x80);
3312 	PHY_WRITE(mac, 0x32, 0xca);
3313 	if (rf->rf_type == BWI_RF_T_BCM2050)
3314 		PHY_WRITE(mac, 0x32, 0xe0);
3315 	PHY_WRITE(mac, 0x35, 0x7c2);
3316 
3317 	bwi_rf_lo_update(mac);
3318 
3319 	PHY_WRITE(mac, 0x26, 0xcc00);
3320 	if (rf->rf_type == BWI_RF_T_BCM2050)
3321 		PHY_WRITE(mac, 0x26, 0xce00);
3322 
3323 	CSR_WRITE_2(sc, BWI_RF_CHAN_EX, 0x1100);
3324 
3325 	PHY_WRITE(mac, 0x2a, 0x88a3);
3326 	if (rf->rf_type == BWI_RF_T_BCM2050)
3327 		PHY_WRITE(mac, 0x2a, 0x88c2);
3328 
3329 	bwi_mac_set_tpctl_11bg(mac, NULL);
3330 	if (sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) {
3331 		bwi_rf_calc_nrssi_slope(mac);
3332 		bwi_rf_set_nrssi_thr(mac);
3333 	}
3334 	bwi_mac_init_tpctl_11bg(mac);
3335 }
3336 
3337 static void
3338 bwi_phy_init_11b_rev5(struct bwi_mac *mac)
3339 {
3340 	struct bwi_softc *sc = mac->mac_sc;
3341 	struct bwi_rf *rf = &mac->mac_rf;
3342 	struct bwi_phy *phy = &mac->mac_phy;
3343 	uint orig_chan;
3344 
3345 	if (phy->phy_version == 1)
3346 		RF_SETBITS(mac, 0x7a, 0x50);
3347 
3348 	if (sc->sc_pci_subvid != PCI_VENDOR_BROADCOM &&
3349 	    sc->sc_pci_subdid != BWI_PCI_SUBDEVICE_BU4306) {
3350 		uint16_t ofs, val;
3351 
3352 		val = 0x2120;
3353 		for (ofs = 0xa8; ofs < 0xc7; ++ofs) {
3354 			PHY_WRITE(mac, ofs, val);
3355 			val += 0x202;
3356 		}
3357 	}
3358 
3359 	PHY_FILT_SETBITS(mac, 0x35, 0xf0ff, 0x700);
3360 
3361 	if (rf->rf_type == BWI_RF_T_BCM2050)
3362 		PHY_WRITE(mac, 0x38, 0x667);
3363 
3364 	if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
3365 		if (rf->rf_type == BWI_RF_T_BCM2050) {
3366 			RF_SETBITS(mac, 0x7a, 0x20);
3367 			RF_SETBITS(mac, 0x51, 0x4);
3368 		}
3369 
3370 		CSR_WRITE_2(sc, BWI_RF_ANTDIV, 0);
3371 
3372 		PHY_SETBITS(mac, 0x802, 0x100);
3373 		PHY_SETBITS(mac, 0x42b, 0x2000);
3374 		PHY_WRITE(mac, 0x1c, 0x186a);
3375 
3376 		PHY_FILT_SETBITS(mac, 0x13, 0xff, 0x1900);
3377 		PHY_FILT_SETBITS(mac, 0x35, 0xffc0, 0x64);
3378 		PHY_FILT_SETBITS(mac, 0x5d, 0xff80, 0xa);
3379 	}
3380 
3381 	/* TODO: bad_frame_preempt? */
3382 
3383 	if (phy->phy_version == 1) {
3384 	    	PHY_WRITE(mac, 0x26, 0xce00);
3385 		PHY_WRITE(mac, 0x21, 0x3763);
3386 		PHY_WRITE(mac, 0x22, 0x1bc3);
3387 		PHY_WRITE(mac, 0x23, 0x6f9);
3388 		PHY_WRITE(mac, 0x24, 0x37e);
3389 	} else
3390 		PHY_WRITE(mac, 0x26, 0xcc00);
3391 	PHY_WRITE(mac, 0x30, 0xc6);
3392 
3393 	CSR_WRITE_2(sc, BWI_BPHY_CTRL, BWI_BPHY_CTRL_INIT);
3394 
3395 	if (phy->phy_version == 1)
3396 		PHY_WRITE(mac, 0x20, 0x3e1c);
3397 	else
3398 		PHY_WRITE(mac, 0x20, 0x301c);
3399 
3400 	if (phy->phy_version == 0)
3401 		CSR_WRITE_2(sc, BWI_PHY_MAGIC_REG1, BWI_PHY_MAGIC_REG1_VAL1);
3402 
3403 	/* Force to channel 7 */
3404 	orig_chan = rf->rf_curchan;
3405 	bwi_rf_set_chan(mac, 7, 0);
3406 
3407 	if (rf->rf_type != BWI_RF_T_BCM2050) {
3408 		RF_WRITE(mac, 0x75, 0x80);
3409 		RF_WRITE(mac, 0x79, 0x81);
3410 	}
3411 
3412 	RF_WRITE(mac, 0x50, 0x20);
3413 	RF_WRITE(mac, 0x50, 0x23);
3414 
3415 	if (rf->rf_type == BWI_RF_T_BCM2050) {
3416 		RF_WRITE(mac, 0x50, 0x20);
3417 		RF_WRITE(mac, 0x5a, 0x70);
3418 	}
3419 
3420 	RF_WRITE(mac, 0x5b, 0x7b);
3421 	RF_WRITE(mac, 0x5c, 0xb0);
3422 	RF_SETBITS(mac, 0x7a, 0x7);
3423 
3424 	bwi_rf_set_chan(mac, orig_chan, 0);
3425 
3426 	PHY_WRITE(mac, 0x14, 0x80);
3427 	PHY_WRITE(mac, 0x32, 0xca);
3428 	PHY_WRITE(mac, 0x2a, 0x88a3);
3429 
3430 	bwi_mac_set_tpctl_11bg(mac, NULL);
3431 
3432 	if (rf->rf_type == BWI_RF_T_BCM2050)
3433 		RF_WRITE(mac, 0x5d, 0xd);
3434 
3435 	CSR_FILT_SETBITS_2(sc, BWI_PHY_MAGIC_REG1, 0xffc0, 0x4);
3436 }
3437 
3438 static void
3439 bwi_phy_init_11b_rev6(struct bwi_mac *mac)
3440 {
3441 	struct bwi_softc *sc = mac->mac_sc;
3442 	struct bwi_rf *rf = &mac->mac_rf;
3443 	struct bwi_phy *phy = &mac->mac_phy;
3444 	uint16_t val, ofs;
3445 	uint orig_chan;
3446 
3447 	PHY_WRITE(mac, 0x3e, 0x817a);
3448 	RF_SETBITS(mac, 0x7a, 0x58);
3449 
3450 	if (rf->rf_rev == 4 || rf->rf_rev == 5) {
3451 		RF_WRITE(mac, 0x51, 0x37);
3452 		RF_WRITE(mac, 0x52, 0x70);
3453 		RF_WRITE(mac, 0x53, 0xb3);
3454 		RF_WRITE(mac, 0x54, 0x9b);
3455 		RF_WRITE(mac, 0x5a, 0x88);
3456 		RF_WRITE(mac, 0x5b, 0x88);
3457 		RF_WRITE(mac, 0x5d, 0x88);
3458 		RF_WRITE(mac, 0x5e, 0x88);
3459 		RF_WRITE(mac, 0x7d, 0x88);
3460 		HFLAGS_SETBITS(mac, BWI_HFLAG_MAGIC1);
3461 	} else if (rf->rf_rev == 8) {
3462 		RF_WRITE(mac, 0x51, 0);
3463 		RF_WRITE(mac, 0x52, 0x40);
3464 		RF_WRITE(mac, 0x53, 0xb7);
3465 		RF_WRITE(mac, 0x54, 0x98);
3466 		RF_WRITE(mac, 0x5a, 0x88);
3467 		RF_WRITE(mac, 0x5b, 0x6b);
3468 		RF_WRITE(mac, 0x5c, 0xf);
3469 		if (sc->sc_card_flags & BWI_CARD_F_ALT_IQ) {
3470 			RF_WRITE(mac, 0x5d, 0xfa);
3471 			RF_WRITE(mac, 0x5e, 0xd8);
3472 		} else {
3473 			RF_WRITE(mac, 0x5d, 0xf5);
3474 			RF_WRITE(mac, 0x5e, 0xb8);
3475 		}
3476 		RF_WRITE(mac, 0x73, 0x3);
3477 		RF_WRITE(mac, 0x7d, 0xa8);
3478 		RF_WRITE(mac, 0x7c, 0x1);
3479 		RF_WRITE(mac, 0x7e, 0x8);
3480 	}
3481 
3482 	val = 0x1e1f;
3483 	for (ofs = 0x88; ofs < 0x98; ++ofs) {
3484 		PHY_WRITE(mac, ofs, val);
3485 		val -= 0x202;
3486 	}
3487 
3488 	val = 0x3e3f;
3489 	for (ofs = 0x98; ofs < 0xa8; ++ofs) {
3490 		PHY_WRITE(mac, ofs, val);
3491 		val -= 0x202;
3492 	}
3493 
3494 	val = 0x2120;
3495 	for (ofs = 0xa8; ofs < 0xc8; ++ofs) {
3496 		PHY_WRITE(mac, ofs, (val & 0x3f3f));
3497 		val += 0x202;
3498 	}
3499 
3500 	if (phy->phy_mode == IEEE80211_MODE_11G) {
3501 		RF_SETBITS(mac, 0x7a, 0x20);
3502 		RF_SETBITS(mac, 0x51, 0x4);
3503 		PHY_SETBITS(mac, 0x802, 0x100);
3504 		PHY_SETBITS(mac, 0x42b, 0x2000);
3505 		PHY_WRITE(mac, 0x5b, 0);
3506 		PHY_WRITE(mac, 0x5c, 0);
3507 	}
3508 
3509 	/* Force to channel 7 */
3510 	orig_chan = rf->rf_curchan;
3511 	if (orig_chan >= 8)
3512 		bwi_rf_set_chan(mac, 1, 0);
3513 	else
3514 		bwi_rf_set_chan(mac, 13, 0);
3515 
3516 	RF_WRITE(mac, 0x50, 0x20);
3517 	RF_WRITE(mac, 0x50, 0x23);
3518 
3519 	DELAY(40);
3520 
3521 	if (rf->rf_rev < 6 || rf->rf_rev == 8) {
3522 		RF_SETBITS(mac, 0x7c, 0x2);
3523 		RF_WRITE(mac, 0x50, 0x20);
3524 	}
3525 	if (rf->rf_rev <= 2) {
3526 		RF_WRITE(mac, 0x7c, 0x20);
3527 		RF_WRITE(mac, 0x5a, 0x70);
3528 		RF_WRITE(mac, 0x5b, 0x7b);
3529 		RF_WRITE(mac, 0x5c, 0xb0);
3530 	}
3531 
3532 	RF_FILT_SETBITS(mac, 0x7a, 0xf8, 0x7);
3533 
3534 	bwi_rf_set_chan(mac, orig_chan, 0);
3535 
3536 	PHY_WRITE(mac, 0x14, 0x200);
3537 	if (rf->rf_rev >= 6)
3538 		PHY_WRITE(mac, 0x2a, 0x88c2);
3539 	else
3540 		PHY_WRITE(mac, 0x2a, 0x8ac0);
3541 	PHY_WRITE(mac, 0x38, 0x668);
3542 
3543 	bwi_mac_set_tpctl_11bg(mac, NULL);
3544 
3545 	if (rf->rf_rev <= 5) {
3546 		PHY_FILT_SETBITS(mac, 0x5d, 0xff80, 0x3);
3547 		if (rf->rf_rev <= 2)
3548 			RF_WRITE(mac, 0x5d, 0xd);
3549 	}
3550 
3551 	if (phy->phy_version == 4) {
3552 		CSR_WRITE_2(sc, BWI_PHY_MAGIC_REG1, BWI_PHY_MAGIC_REG1_VAL2);
3553 		PHY_CLRBITS(mac, 0x61, 0xf000);
3554 	} else {
3555 		PHY_FILT_SETBITS(mac, 0x2, 0xffc0, 0x4);
3556 	}
3557 
3558 	if (phy->phy_mode == IEEE80211_MODE_11B) {
3559 		CSR_WRITE_2(sc, BWI_BBP_ATTEN, BWI_BBP_ATTEN_MAGIC2);
3560 		PHY_WRITE(mac, 0x16, 0x410);
3561 		PHY_WRITE(mac, 0x17, 0x820);
3562 		PHY_WRITE(mac, 0x62, 0x7);
3563 
3564 		bwi_rf_init_bcm2050(mac);
3565 		bwi_rf_lo_update(mac);
3566 		if (sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) {
3567 			bwi_rf_calc_nrssi_slope(mac);
3568 			bwi_rf_set_nrssi_thr(mac);
3569 		}
3570 		bwi_mac_init_tpctl_11bg(mac);
3571 	} else
3572 		CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0);
3573 }
3574 
3575 static void
3576 bwi_phy_config_11g(struct bwi_mac *mac)
3577 {
3578 	struct bwi_softc *sc = mac->mac_sc;
3579 	struct bwi_phy *phy = &mac->mac_phy;
3580 	const uint16_t *tbl;
3581 	uint16_t wrd_ofs1, wrd_ofs2;
3582 	int i, n;
3583 
3584 	if (phy->phy_rev == 1) {
3585 		PHY_WRITE(mac, 0x406, 0x4f19);
3586 		PHY_FILT_SETBITS(mac, 0x429, 0xfc3f, 0x340);
3587 		PHY_WRITE(mac, 0x42c, 0x5a);
3588 		PHY_WRITE(mac, 0x427, 0x1a);
3589 
3590 		/* Fill frequency table */
3591 		for (i = 0; i < __arraycount(bwi_phy_freq_11g_rev1); ++i) {
3592 			bwi_tbl_write_2(mac, BWI_PHYTBL_FREQ + i,
3593 			    bwi_phy_freq_11g_rev1[i]);
3594 		}
3595 
3596 		/* Fill noise table */
3597 		for (i = 0; i < __arraycount(bwi_phy_noise_11g_rev1); ++i) {
3598 			bwi_tbl_write_2(mac, BWI_PHYTBL_NOISE + i,
3599 			    bwi_phy_noise_11g_rev1[i]);
3600 		}
3601 
3602 		/* Fill rotor table */
3603 		for (i = 0; i < __arraycount(bwi_phy_rotor_11g_rev1); ++i) {
3604 			/* NB: data length is 4 bytes */
3605 			bwi_tbl_write_4(mac, BWI_PHYTBL_ROTOR + i,
3606 			    bwi_phy_rotor_11g_rev1[i]);
3607 		}
3608 	} else {
3609 		bwi_nrssi_write(mac, 0xba98, (int16_t)0x7654); /* XXX */
3610 
3611 		if (phy->phy_rev == 2) {
3612 			PHY_WRITE(mac, 0x4c0, 0x1861);
3613 			PHY_WRITE(mac, 0x4c1, 0x271);
3614 		} else if (phy->phy_rev > 2) {
3615 			PHY_WRITE(mac, 0x4c0, 0x98);
3616 			PHY_WRITE(mac, 0x4c1, 0x70);
3617 			PHY_WRITE(mac, 0x4c9, 0x80);
3618 		}
3619 		PHY_SETBITS(mac, 0x42b, 0x800);
3620 
3621 		/* Fill RSSI table */
3622 		for (i = 0; i < 64; ++i)
3623 			bwi_tbl_write_2(mac, BWI_PHYTBL_RSSI + i, i);
3624 
3625 		/* Fill noise table */
3626 		for (i = 0; i < __arraycount(bwi_phy_noise_11g); ++i) {
3627 			bwi_tbl_write_2(mac, BWI_PHYTBL_NOISE + i,
3628 			    bwi_phy_noise_11g[i]);
3629 		}
3630 	}
3631 
3632 	/*
3633 	 * Fill noise scale table
3634 	 */
3635 	if (phy->phy_rev <= 2) {
3636 		tbl = bwi_phy_noise_scale_11g_rev2;
3637 		n = __arraycount(bwi_phy_noise_scale_11g_rev2);
3638 	} else if (phy->phy_rev >= 7 && (PHY_READ(mac, 0x449) & 0x200)) {
3639 		tbl = bwi_phy_noise_scale_11g_rev7;
3640 		n = __arraycount(bwi_phy_noise_scale_11g_rev7);
3641 	} else {
3642 		tbl = bwi_phy_noise_scale_11g;
3643 		n = __arraycount(bwi_phy_noise_scale_11g);
3644 	}
3645 	for (i = 0; i < n; ++i)
3646 		bwi_tbl_write_2(mac, BWI_PHYTBL_NOISE_SCALE + i, tbl[i]);
3647 
3648 	/*
3649 	 * Fill sigma square table
3650 	 */
3651 	if (phy->phy_rev == 2) {
3652 		tbl = bwi_phy_sigma_sq_11g_rev2;
3653 		n = __arraycount(bwi_phy_sigma_sq_11g_rev2);
3654 	} else if (phy->phy_rev > 2 && phy->phy_rev <= 8) {
3655 		tbl = bwi_phy_sigma_sq_11g_rev7;
3656 		n = __arraycount(bwi_phy_sigma_sq_11g_rev7);
3657 	} else {
3658 		tbl = NULL;
3659 		n = 0;
3660 	}
3661 	for (i = 0; i < n; ++i)
3662 		bwi_tbl_write_2(mac, BWI_PHYTBL_SIGMA_SQ + i, tbl[i]);
3663 
3664 	if (phy->phy_rev == 1) {
3665 		/* Fill delay table */
3666 		for (i = 0; i < __arraycount(bwi_phy_delay_11g_rev1); ++i) {
3667 			bwi_tbl_write_4(mac, BWI_PHYTBL_DELAY + i,
3668 			    bwi_phy_delay_11g_rev1[i]);
3669 		}
3670 
3671 		/* Fill WRSSI (Wide-Band RSSI) table */
3672 		for (i = 4; i < 20; ++i)
3673 			bwi_tbl_write_2(mac, BWI_PHYTBL_WRSSI_REV1 + i, 0x20);
3674 
3675 		bwi_phy_config_agc(mac);
3676 
3677 		wrd_ofs1 = 0x5001;
3678 		wrd_ofs2 = 0x5002;
3679 	} else {
3680 		/* Fill WRSSI (Wide-Band RSSI) table */
3681 		for (i = 0; i < 0x20; ++i)
3682 			bwi_tbl_write_2(mac, BWI_PHYTBL_WRSSI + i, 0x820);
3683 
3684 		bwi_phy_config_agc(mac);
3685 
3686 		PHY_READ(mac, 0x400);	/* Dummy read */
3687 		PHY_WRITE(mac, 0x403, 0x1000);
3688 		bwi_tbl_write_2(mac, 0x3c02, 0xf);
3689 		bwi_tbl_write_2(mac, 0x3c03, 0x14);
3690 
3691 		wrd_ofs1 = 0x401;
3692 		wrd_ofs2 = 0x402;
3693 	}
3694 
3695 	if (!(BWI_IS_BRCM_BU4306(sc) && sc->sc_pci_revid == 0x17)) {
3696 		bwi_tbl_write_2(mac, wrd_ofs1, 0x2);
3697 		bwi_tbl_write_2(mac, wrd_ofs2, 0x1);
3698 	}
3699 
3700 	/* phy->phy_flags & BWI_PHY_F_LINKED ? */
3701 	if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9)
3702 		PHY_WRITE(mac, 0x46e, 0x3cf);
3703 }
3704 
3705 /*
3706  * Configure Automatic Gain Controller
3707  */
3708 static void
3709 bwi_phy_config_agc(struct bwi_mac *mac)
3710 {
3711 	struct bwi_phy *phy = &mac->mac_phy;
3712 	uint16_t ofs;
3713 
3714 	ofs = phy->phy_rev == 1 ? 0x4c00 : 0;
3715 
3716 	bwi_tbl_write_2(mac, ofs, 0xfe);
3717 	bwi_tbl_write_2(mac, ofs + 1, 0xd);
3718 	bwi_tbl_write_2(mac, ofs + 2, 0x13);
3719 	bwi_tbl_write_2(mac, ofs + 3, 0x19);
3720 
3721 	if (phy->phy_rev == 1) {
3722 		bwi_tbl_write_2(mac, 0x1800, 0x2710);
3723 		bwi_tbl_write_2(mac, 0x1801, 0x9b83);
3724 		bwi_tbl_write_2(mac, 0x1802, 0x9b83);
3725 		bwi_tbl_write_2(mac, 0x1803, 0xf8d);
3726 		PHY_WRITE(mac, 0x455, 0x4);
3727 	}
3728 
3729 	PHY_FILT_SETBITS(mac, 0x4a5, 0xff, 0x5700);
3730 	PHY_FILT_SETBITS(mac, 0x41a, 0xff80, 0xf);
3731 	PHY_FILT_SETBITS(mac, 0x41a, 0xc07f, 0x2b80);
3732 	PHY_FILT_SETBITS(mac, 0x48c, 0xf0ff, 0x300);
3733 
3734 	RF_SETBITS(mac, 0x7a, 0x8);
3735 
3736 	PHY_FILT_SETBITS(mac, 0x4a0, 0xfff0, 0x8);
3737 	PHY_FILT_SETBITS(mac, 0x4a1, 0xf0ff, 0x600);
3738 	PHY_FILT_SETBITS(mac, 0x4a2, 0xf0ff, 0x700);
3739 	PHY_FILT_SETBITS(mac, 0x4a0, 0xf0ff, 0x100);
3740 
3741 	if (phy->phy_rev == 1)
3742 		PHY_FILT_SETBITS(mac, 0x4a2, 0xfff0, 0x7);
3743 
3744 	PHY_FILT_SETBITS(mac, 0x488, 0xff00, 0x1c);
3745 	PHY_FILT_SETBITS(mac, 0x488, 0xc0ff, 0x200);
3746 	PHY_FILT_SETBITS(mac, 0x496, 0xff00, 0x1c);
3747 	PHY_FILT_SETBITS(mac, 0x489, 0xff00, 0x20);
3748 	PHY_FILT_SETBITS(mac, 0x489, 0xc0ff, 0x200);
3749 	PHY_FILT_SETBITS(mac, 0x482, 0xff00, 0x2e);
3750 	PHY_FILT_SETBITS(mac, 0x496, 0xff, 0x1a00);
3751 	PHY_FILT_SETBITS(mac, 0x481, 0xff00, 0x28);
3752 	PHY_FILT_SETBITS(mac, 0x481, 0xff, 0x2c00);
3753 
3754 	if (phy->phy_rev == 1) {
3755 		PHY_WRITE(mac, 0x430, 0x92b);
3756 		PHY_FILT_SETBITS(mac, 0x41b, 0xffe1, 0x2);
3757 	} else {
3758 		PHY_CLRBITS(mac, 0x41b, 0x1e);
3759 		PHY_WRITE(mac, 0x41f, 0x287a);
3760 		PHY_FILT_SETBITS(mac, 0x420, 0xfff0, 0x4);
3761 
3762 		if (phy->phy_rev >= 6) {
3763 			PHY_WRITE(mac, 0x422, 0x287a);
3764 			PHY_FILT_SETBITS(mac, 0x420, 0xfff, 0x3000);
3765 		}
3766 	}
3767 
3768 	PHY_FILT_SETBITS(mac, 0x4a8, 0x8080, 0x7874);
3769 	PHY_WRITE(mac, 0x48e, 0x1c00);
3770 
3771 	if (phy->phy_rev == 1) {
3772 		PHY_FILT_SETBITS(mac, 0x4ab, 0xf0ff, 0x600);
3773 		PHY_WRITE(mac, 0x48b, 0x5e);
3774 		PHY_FILT_SETBITS(mac, 0x48c, 0xff00, 0x1e);
3775 		PHY_WRITE(mac, 0x48d, 0x2);
3776 	}
3777 
3778 	bwi_tbl_write_2(mac, ofs + 0x800, 0);
3779 	bwi_tbl_write_2(mac, ofs + 0x801, 7);
3780 	bwi_tbl_write_2(mac, ofs + 0x802, 16);
3781 	bwi_tbl_write_2(mac, ofs + 0x803, 28);
3782 
3783 	if (phy->phy_rev >= 6) {
3784 		PHY_CLRBITS(mac, 0x426, 0x3);
3785 		PHY_CLRBITS(mac, 0x426, 0x1000);
3786 	}
3787 }
3788 
3789 static void
3790 bwi_set_gains(struct bwi_mac *mac, const struct bwi_gains *gains)
3791 {
3792 	struct bwi_phy *phy = &mac->mac_phy;
3793 	uint16_t tbl_gain_ofs1, tbl_gain_ofs2, tbl_gain;
3794 	int i;
3795 
3796 	if (phy->phy_rev <= 1) {
3797 		tbl_gain_ofs1 = 0x5000;
3798 		tbl_gain_ofs2 = tbl_gain_ofs1 + 16;
3799 	} else {
3800 		tbl_gain_ofs1 = 0x400;
3801 		tbl_gain_ofs2 = tbl_gain_ofs1 + 8;
3802 	}
3803 
3804 	for (i = 0; i < 4; ++i) {
3805 		if (gains != NULL) {
3806 			tbl_gain = gains->tbl_gain1;
3807 		} else {
3808 			/* Bit swap */
3809 			tbl_gain = (i & 0x1) << 1;
3810 			tbl_gain |= (i & 0x2) >> 1;
3811 		}
3812 		bwi_tbl_write_2(mac, tbl_gain_ofs1 + i, tbl_gain);
3813 	}
3814 
3815 	for (i = 0; i < 16; ++i) {
3816 		if (gains != NULL)
3817 			tbl_gain = gains->tbl_gain2;
3818 		else
3819 			tbl_gain = i;
3820 		bwi_tbl_write_2(mac, tbl_gain_ofs2 + i, tbl_gain);
3821 	}
3822 
3823 	if (gains == NULL || gains->phy_gain != -1) {
3824 		uint16_t phy_gain1, phy_gain2;
3825 
3826 		if (gains != NULL) {
3827 			phy_gain1 =
3828 			((uint16_t)gains->phy_gain << 14) |
3829 			((uint16_t)gains->phy_gain << 6);
3830 			phy_gain2 = phy_gain1;
3831 		} else {
3832 			phy_gain1 = 0x4040;
3833 			phy_gain2 = 0x4000;
3834 		}
3835 		PHY_FILT_SETBITS(mac, 0x4a0, 0xbfbf, phy_gain1);
3836 		PHY_FILT_SETBITS(mac, 0x4a1, 0xbfbf, phy_gain1);
3837 		PHY_FILT_SETBITS(mac, 0x4a2, 0xbfbf, phy_gain2);
3838 	}
3839 	bwi_mac_dummy_xmit(mac);
3840 }
3841 
3842 static void
3843 bwi_phy_clear_state(struct bwi_phy *phy)
3844 {
3845 	phy->phy_flags &= ~BWI_CLEAR_PHY_FLAGS;
3846 }
3847 
3848 /* RF */
3849 
3850 static int16_t
3851 bwi_nrssi_11g(struct bwi_mac *mac)
3852 {
3853 	int16_t val;
3854 
3855 #define NRSSI_11G_MASK		0x3f00
3856 	val = (int16_t)__SHIFTOUT(PHY_READ(mac, 0x47f), NRSSI_11G_MASK);
3857 	if (val >= 32)
3858 		val -= 64;
3859 
3860 	return (val);
3861 #undef NRSSI_11G_MASK
3862 }
3863 
3864 static struct bwi_rf_lo *
3865 bwi_get_rf_lo(struct bwi_mac *mac, uint16_t rf_atten, uint16_t bbp_atten)
3866 {
3867 	int n;
3868 
3869 	n = rf_atten + (14 * (bbp_atten / 2));
3870 	KASSERT(n < BWI_RFLO_MAX);
3871 
3872 	return (&mac->mac_rf.rf_lo[n]);
3873 }
3874 
3875 static int
3876 bwi_rf_lo_isused(struct bwi_mac *mac, const struct bwi_rf_lo *lo)
3877 {
3878 	struct bwi_rf *rf = &mac->mac_rf;
3879 	int idx;
3880 
3881 	idx = lo - rf->rf_lo;
3882 	KASSERT(idx >= 0 && idx < BWI_RFLO_MAX);
3883 
3884 	return (isset(rf->rf_lo_used, idx));
3885 }
3886 
3887 static void
3888 bwi_rf_write(struct bwi_mac *mac, uint16_t ctrl, uint16_t data)
3889 {
3890 	struct bwi_softc *sc = mac->mac_sc;
3891 
3892 	CSR_WRITE_2(sc, BWI_RF_CTRL, ctrl);
3893 	CSR_WRITE_2(sc, BWI_RF_DATA_LO, data);
3894 }
3895 
3896 static uint16_t
3897 bwi_rf_read(struct bwi_mac *mac, uint16_t ctrl)
3898 {
3899 	struct bwi_rf *rf = &mac->mac_rf;
3900 	struct bwi_softc *sc = mac->mac_sc;
3901 
3902 	ctrl |= rf->rf_ctrl_rd;
3903 	if (rf->rf_ctrl_adj) {
3904 		/* XXX */
3905 		if (ctrl < 0x70)
3906 			ctrl += 0x80;
3907 		else if (ctrl < 0x80)
3908 			ctrl += 0x70;
3909 	}
3910 
3911 	CSR_WRITE_2(sc, BWI_RF_CTRL, ctrl);
3912 	return (CSR_READ_2(sc, BWI_RF_DATA_LO));
3913 }
3914 
3915 static int
3916 bwi_rf_attach(struct bwi_mac *mac)
3917 {
3918 	struct bwi_softc *sc = mac->mac_sc;
3919 	struct bwi_phy *phy = &mac->mac_phy;
3920 	struct bwi_rf *rf = &mac->mac_rf;
3921 	uint16_t type, manu;
3922 	uint8_t rev;
3923 
3924 	/*
3925 	 * Get RF manufacture/type/revision
3926 	 */
3927 	if (sc->sc_bbp_id == BWI_BBPID_BCM4317) {
3928 		/*
3929 		 * Fake a BCM2050 RF
3930 		 */
3931 		manu = BWI_RF_MANUFACT_BCM;
3932 		type = BWI_RF_T_BCM2050;
3933 		if (sc->sc_bbp_rev == 0)
3934 			rev = 3;
3935 		else if (sc->sc_bbp_rev == 1)
3936 			rev = 4;
3937 		else
3938 			rev = 5;
3939 	} else {
3940 		uint32_t val;
3941 
3942 		CSR_WRITE_2(sc, BWI_RF_CTRL, BWI_RF_CTRL_RFINFO);
3943 		val = CSR_READ_2(sc, BWI_RF_DATA_HI);
3944 		val <<= 16;
3945 
3946 		CSR_WRITE_2(sc, BWI_RF_CTRL, BWI_RF_CTRL_RFINFO);
3947 		val |= CSR_READ_2(sc, BWI_RF_DATA_LO);
3948 
3949 		manu = __SHIFTOUT(val, BWI_RFINFO_MANUFACT_MASK);
3950 		type = __SHIFTOUT(val, BWI_RFINFO_TYPE_MASK);
3951 		rev = __SHIFTOUT(val, BWI_RFINFO_REV_MASK);
3952 	}
3953 	aprint_normal_dev(sc->sc_dev, "RF manu 0x%03x, type 0x%04x, rev %u\n",
3954 	    manu, type, rev);
3955 
3956 	/*
3957 	 * Verify whether the RF is supported
3958 	 */
3959 	rf->rf_ctrl_rd = 0;
3960 	rf->rf_ctrl_adj = 0;
3961 	switch (phy->phy_mode) {
3962 	case IEEE80211_MODE_11A:
3963 		if (manu != BWI_RF_MANUFACT_BCM ||
3964 		    type != BWI_RF_T_BCM2060 ||
3965 		    rev != 1) {
3966 			aprint_error_dev(sc->sc_dev,
3967 			    "only BCM2060 rev 1 RF is supported for"
3968 			    " 11A PHY\n");
3969 			return (ENXIO);
3970 		}
3971 		rf->rf_ctrl_rd = BWI_RF_CTRL_RD_11A;
3972 		rf->rf_on = bwi_rf_on_11a;
3973 		rf->rf_off = bwi_rf_off_11a;
3974 		rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2060;
3975 		break;
3976 	case IEEE80211_MODE_11B:
3977 		if (type == BWI_RF_T_BCM2050) {
3978 			rf->rf_ctrl_rd = BWI_RF_CTRL_RD_11BG;
3979 			rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2050;
3980 		} else if (type == BWI_RF_T_BCM2053) {
3981 			rf->rf_ctrl_adj = 1;
3982 			rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2053;
3983 		} else {
3984 			aprint_error_dev(sc->sc_dev,
3985 			    "only BCM2050/BCM2053 RF is supported for"
3986 			    " 11B phy\n");
3987 			return (ENXIO);
3988 		}
3989 		rf->rf_on = bwi_rf_on_11bg;
3990 		rf->rf_off = bwi_rf_off_11bg;
3991 		rf->rf_calc_nrssi_slope = bwi_rf_calc_nrssi_slope_11b;
3992 		rf->rf_set_nrssi_thr = bwi_rf_set_nrssi_thr_11b;
3993 		if (phy->phy_rev == 6)
3994 			rf->rf_lo_update = bwi_rf_lo_update_11g;
3995 		else
3996 			rf->rf_lo_update = bwi_rf_lo_update_11b;
3997 		break;
3998 	case IEEE80211_MODE_11G:
3999 		if (type != BWI_RF_T_BCM2050) {
4000 			aprint_error_dev(sc->sc_dev,
4001 			    "only BCM2050 RF is supported for"
4002 			    " 11G PHY\n");
4003 			return (ENXIO);
4004 		}
4005 		rf->rf_ctrl_rd = BWI_RF_CTRL_RD_11BG;
4006 		rf->rf_on = bwi_rf_on_11bg;
4007 		if (mac->mac_rev >= 5)
4008 			rf->rf_off = bwi_rf_off_11g_rev5;
4009 		else
4010 			rf->rf_off = bwi_rf_off_11bg;
4011 		rf->rf_calc_nrssi_slope = bwi_rf_calc_nrssi_slope_11g;
4012 		rf->rf_set_nrssi_thr = bwi_rf_set_nrssi_thr_11g;
4013 		rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2050;
4014 		rf->rf_lo_update = bwi_rf_lo_update_11g;
4015 		break;
4016 	default:
4017 		aprint_error_dev(sc->sc_dev, "unsupported PHY mode\n");
4018 		return (ENXIO);
4019 	}
4020 
4021 	rf->rf_type = type;
4022 	rf->rf_rev = rev;
4023 	rf->rf_manu = manu;
4024 	rf->rf_curchan = IEEE80211_CHAN_ANY;
4025 	rf->rf_ant_mode = BWI_ANT_MODE_AUTO;
4026 
4027 	return (0);
4028 }
4029 
4030 static void
4031 bwi_rf_set_chan(struct bwi_mac *mac, uint chan, int work_around)
4032 {
4033 	struct bwi_softc *sc = mac->mac_sc;
4034 
4035 	if (chan == IEEE80211_CHAN_ANY)
4036 		return;
4037 
4038 	MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_CHAN, chan);
4039 
4040 	/* TODO: 11A */
4041 
4042 	if (work_around)
4043 		bwi_rf_workaround(mac, chan);
4044 
4045 	CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(chan));
4046 
4047 	if (chan == 14) {
4048 		if (sc->sc_locale == BWI_SPROM_LOCALE_JAPAN)
4049 			HFLAGS_CLRBITS(mac, BWI_HFLAG_NOT_JAPAN);
4050 		else
4051 			HFLAGS_SETBITS(mac, BWI_HFLAG_NOT_JAPAN);
4052 		CSR_SETBITS_2(sc, BWI_RF_CHAN_EX, (1 << 11)); /* XXX */
4053 	} else {
4054 		CSR_CLRBITS_2(sc, BWI_RF_CHAN_EX, 0x840); /* XXX */
4055 	}
4056 	DELAY(8000);	/* DELAY(2000); */
4057 
4058 	mac->mac_rf.rf_curchan = chan;
4059 }
4060 
4061 static void
4062 bwi_rf_get_gains(struct bwi_mac *mac)
4063 {
4064 #define SAVE_PHY_MAX	15
4065 #define SAVE_RF_MAX	3
4066 	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
4067 	    { 0x52, 0x43, 0x7a };
4068 	static const uint16_t save_phy_regs[SAVE_PHY_MAX] = {
4069 	    0x0429, 0x0001, 0x0811, 0x0812,
4070 	    0x0814, 0x0815, 0x005a, 0x0059,
4071 	    0x0058, 0x000a, 0x0003, 0x080f,
4072 	    0x0810, 0x002b, 0x0015
4073 	};
4074 
4075 	struct bwi_phy *phy = &mac->mac_phy;
4076 	struct bwi_rf *rf = &mac->mac_rf;
4077 	uint16_t save_phy[SAVE_PHY_MAX];
4078 	uint16_t save_rf[SAVE_RF_MAX];
4079 	uint16_t trsw;
4080 	int i, j, loop1_max, loop1, loop2;
4081 
4082 	/*
4083 	 * Save PHY/RF registers for later restoration
4084 	 */
4085 	for (i = 0; i < SAVE_PHY_MAX; ++i)
4086 		save_phy[i] = PHY_READ(mac, save_phy_regs[i]);
4087 	PHY_READ(mac, 0x2d); /* dummy read */
4088 
4089 	for (i = 0; i < SAVE_RF_MAX; ++i)
4090 		save_rf[i] = RF_READ(mac, save_rf_regs[i]);
4091 
4092 	PHY_CLRBITS(mac, 0x429, 0xc000);
4093 	PHY_SETBITS(mac, 0x1, 0x8000);
4094 
4095 	PHY_SETBITS(mac, 0x811, 0x2);
4096 	PHY_CLRBITS(mac, 0x812, 0x2);
4097 	PHY_SETBITS(mac, 0x811, 0x1);
4098 	PHY_CLRBITS(mac, 0x812, 0x1);
4099 
4100 	PHY_SETBITS(mac, 0x814, 0x1);
4101 	PHY_CLRBITS(mac, 0x815, 0x1);
4102 	PHY_SETBITS(mac, 0x814, 0x2);
4103 	PHY_CLRBITS(mac, 0x815, 0x2);
4104 
4105 	PHY_SETBITS(mac, 0x811, 0xc);
4106 	PHY_SETBITS(mac, 0x812, 0xc);
4107 	PHY_SETBITS(mac, 0x811, 0x30);
4108 	PHY_FILT_SETBITS(mac, 0x812, 0xffcf, 0x10);
4109 
4110 	PHY_WRITE(mac, 0x5a, 0x780);
4111 	PHY_WRITE(mac, 0x59, 0xc810);
4112 	PHY_WRITE(mac, 0x58, 0xd);
4113 	PHY_SETBITS(mac, 0xa, 0x2000);
4114 
4115 	PHY_SETBITS(mac, 0x814, 0x4);
4116 	PHY_CLRBITS(mac, 0x815, 0x4);
4117 
4118 	PHY_FILT_SETBITS(mac, 0x3, 0xff9f, 0x40);
4119 
4120 	if (rf->rf_rev == 8) {
4121 		loop1_max = 15;
4122 		RF_WRITE(mac, 0x43, loop1_max);
4123 	} else {
4124 		loop1_max = 9;
4125 	    	RF_WRITE(mac, 0x52, 0x0);
4126 		RF_FILT_SETBITS(mac, 0x43, 0xfff0, loop1_max);
4127 	}
4128 
4129 	bwi_phy_set_bbp_atten(mac, 11);
4130 
4131 	if (phy->phy_rev >= 3)
4132 		PHY_WRITE(mac, 0x80f, 0xc020);
4133 	else
4134 		PHY_WRITE(mac, 0x80f, 0x8020);
4135 	PHY_WRITE(mac, 0x810, 0);
4136 
4137 	PHY_FILT_SETBITS(mac, 0x2b, 0xffc0, 0x1);
4138 	PHY_FILT_SETBITS(mac, 0x2b, 0xc0ff, 0x800);
4139 	PHY_SETBITS(mac, 0x811, 0x100);
4140 	PHY_CLRBITS(mac, 0x812, 0x3000);
4141 
4142 	if ((mac->mac_sc->sc_card_flags & BWI_CARD_F_EXT_LNA) &&
4143 	    phy->phy_rev >= 7) {
4144 		PHY_SETBITS(mac, 0x811, 0x800);
4145 		PHY_SETBITS(mac, 0x812, 0x8000);
4146 	}
4147 	RF_CLRBITS(mac, 0x7a, 0xff08);
4148 
4149 	/*
4150 	 * Find out 'loop1/loop2', which will be used to calculate
4151 	 * max loopback gain later
4152 	 */
4153 	j = 0;
4154 	for (i = 0; i < loop1_max; ++i) {
4155 		for (j = 0; j < 16; ++j) {
4156 			RF_WRITE(mac, 0x43, i);
4157 
4158 			if (bwi_rf_gain_max_reached(mac, j))
4159 				goto loop1_exit;
4160 		}
4161 	}
4162 loop1_exit:
4163 	loop1 = i;
4164 	loop2 = j;
4165 
4166 	/*
4167 	 * Find out 'trsw', which will be used to calculate
4168 	 * TRSW(TX/RX switch) RX gain later
4169 	 */
4170 	if (loop2 >= 8) {
4171 		PHY_SETBITS(mac, 0x812, 0x30);
4172 		trsw = 0x1b;
4173 		for (i = loop2 - 8; i < 16; ++i) {
4174 			trsw -= 3;
4175 			if (bwi_rf_gain_max_reached(mac, i))
4176 				break;
4177 		}
4178 	} else {
4179 		trsw = 0x18;
4180 	}
4181 
4182 	/*
4183 	 * Restore saved PHY/RF registers
4184 	 */
4185 	/* First 4 saved PHY registers need special processing */
4186 	for (i = 4; i < SAVE_PHY_MAX; ++i)
4187 		PHY_WRITE(mac, save_phy_regs[i], save_phy[i]);
4188 
4189 	bwi_phy_set_bbp_atten(mac, mac->mac_tpctl.bbp_atten);
4190 
4191 	for (i = 0; i < SAVE_RF_MAX; ++i)
4192 		RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
4193 
4194 	PHY_WRITE(mac, save_phy_regs[2], save_phy[2] | 0x3);
4195 	DELAY(10);
4196 	PHY_WRITE(mac, save_phy_regs[2], save_phy[2]);
4197 	PHY_WRITE(mac, save_phy_regs[3], save_phy[3]);
4198 	PHY_WRITE(mac, save_phy_regs[0], save_phy[0]);
4199 	PHY_WRITE(mac, save_phy_regs[1], save_phy[1]);
4200 
4201 	/*
4202 	 * Calculate gains
4203 	 */
4204 	rf->rf_lo_gain = (loop2 * 6) - (loop1 * 4) - 11;
4205 	rf->rf_rx_gain = trsw * 2;
4206 	DPRINTF(mac->mac_sc, BWI_DBG_RF | BWI_DBG_INIT,
4207 	    "lo gain: %u, rx gain: %u\n",
4208 	    rf->rf_lo_gain, rf->rf_rx_gain);
4209 
4210 #undef SAVE_RF_MAX
4211 #undef SAVE_PHY_MAX
4212 }
4213 
4214 static void
4215 bwi_rf_init(struct bwi_mac *mac)
4216 {
4217 	struct bwi_rf *rf = &mac->mac_rf;
4218 
4219 	if (rf->rf_type == BWI_RF_T_BCM2060) {
4220 		/* TODO: 11A */
4221 	} else {
4222 		if (rf->rf_flags & BWI_RF_F_INITED)
4223 			RF_WRITE(mac, 0x78, rf->rf_calib);
4224 		else
4225 			bwi_rf_init_bcm2050(mac);
4226 	}
4227 }
4228 
4229 static void
4230 bwi_rf_off_11a(struct bwi_mac *mac)
4231 {
4232 	RF_WRITE(mac, 0x4, 0xff);
4233 	RF_WRITE(mac, 0x5, 0xfb);
4234 
4235 	PHY_SETBITS(mac, 0x10, 0x8);
4236 	PHY_SETBITS(mac, 0x11, 0x8);
4237 
4238 	PHY_WRITE(mac, 0x15, 0xaa00);
4239 }
4240 
4241 static void
4242 bwi_rf_off_11bg(struct bwi_mac *mac)
4243 {
4244 	PHY_WRITE(mac, 0x15, 0xaa00);
4245 }
4246 
4247 static void
4248 bwi_rf_off_11g_rev5(struct bwi_mac *mac)
4249 {
4250 	PHY_SETBITS(mac, 0x811, 0x8c);
4251 	PHY_CLRBITS(mac, 0x812, 0x8c);
4252 }
4253 
4254 static void
4255 bwi_rf_workaround(struct bwi_mac *mac, uint chan)
4256 {
4257 	struct bwi_softc *sc = mac->mac_sc;
4258 	struct bwi_rf *rf = &mac->mac_rf;
4259 
4260 	if (chan == IEEE80211_CHAN_ANY) {
4261 		aprint_error_dev(sc->sc_dev, "%s invalid channel!\n",
4262 		    __func__);
4263 		return;
4264 	}
4265 
4266 	if (rf->rf_type != BWI_RF_T_BCM2050 || rf->rf_rev >= 6)
4267 		return;
4268 
4269 	if (chan <= 10)
4270 		CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(chan + 4));
4271 	else
4272 		CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(1));
4273 	DELAY(1000);
4274 	CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(chan));
4275 }
4276 
4277 static struct bwi_rf_lo *
4278 bwi_rf_lo_find(struct bwi_mac *mac, const struct bwi_tpctl *tpctl)
4279 {
4280 	uint16_t rf_atten, bbp_atten;
4281 	int remap_rf_atten;
4282 
4283 	remap_rf_atten = 1;
4284 	if (tpctl == NULL) {
4285 		bbp_atten = 2;
4286 		rf_atten = 3;
4287 	} else {
4288 		if (tpctl->tp_ctrl1 == 3)
4289 			remap_rf_atten = 0;
4290 
4291 		bbp_atten = tpctl->bbp_atten;
4292 		rf_atten = tpctl->rf_atten;
4293 
4294 		if (bbp_atten > 6)
4295 			bbp_atten = 6;
4296 	}
4297 
4298 	if (remap_rf_atten) {
4299 #define MAP_MAX	10
4300 		static const uint16_t map[MAP_MAX] =
4301 		    { 11, 10, 11, 12, 13, 12, 13, 12, 13, 12 };
4302 #if 0
4303 		KASSERT(rf_atten < MAP_MAX);
4304 		rf_atten = map[rf_atten];
4305 #else
4306 		if (rf_atten >= MAP_MAX) {
4307 			rf_atten = 0;	/* XXX */
4308 		} else {
4309 			rf_atten = map[rf_atten];
4310 		}
4311 #endif
4312 #undef MAP_MAX
4313 	}
4314 
4315 	return (bwi_get_rf_lo(mac, rf_atten, bbp_atten));
4316 }
4317 
4318 static void
4319 bwi_rf_lo_adjust(struct bwi_mac *mac, const struct bwi_tpctl *tpctl)
4320 {
4321 	const struct bwi_rf_lo *lo;
4322 
4323 	lo = bwi_rf_lo_find(mac, tpctl);
4324 	RF_LO_WRITE(mac, lo);
4325 }
4326 
4327 static void
4328 bwi_rf_lo_write(struct bwi_mac *mac, const struct bwi_rf_lo *lo)
4329 {
4330 	uint16_t val;
4331 
4332 	val = (uint8_t)lo->ctrl_lo;
4333 	val |= ((uint8_t)lo->ctrl_hi) << 8;
4334 
4335 	PHY_WRITE(mac, BWI_PHYR_RF_LO, val);
4336 }
4337 
4338 static int
4339 bwi_rf_gain_max_reached(struct bwi_mac *mac, int idx)
4340 {
4341 	PHY_FILT_SETBITS(mac, 0x812, 0xf0ff, idx << 8);
4342 	PHY_FILT_SETBITS(mac, 0x15, 0xfff, 0xa000);
4343 	PHY_SETBITS(mac, 0x15, 0xf000);
4344 
4345 	DELAY(20);
4346 
4347 	return ((PHY_READ(mac, 0x2d) >= 0xdfc));
4348 }
4349 
4350 /* XXX use bitmap array */
4351 static uint16_t
4352 bwi_bitswap4(uint16_t val)
4353 {
4354 	uint16_t ret;
4355 
4356 	ret = (val & 0x8) >> 3;
4357 	ret |= (val & 0x4) >> 1;
4358 	ret |= (val & 0x2) << 1;
4359 	ret |= (val & 0x1) << 3;
4360 
4361 	return (ret);
4362 }
4363 
4364 static uint16_t
4365 bwi_phy812_value(struct bwi_mac *mac, uint16_t lpd)
4366 {
4367 	struct bwi_softc *sc = mac->mac_sc;
4368 	struct bwi_phy *phy = &mac->mac_phy;
4369 	struct bwi_rf *rf = &mac->mac_rf;
4370 	uint16_t lo_gain, ext_lna, loop;
4371 
4372 	if ((phy->phy_flags & BWI_PHY_F_LINKED) == 0)
4373 		return (0);
4374 
4375 	lo_gain = rf->rf_lo_gain;
4376 	if (rf->rf_rev == 8)
4377 		lo_gain += 0x3e;
4378 	else
4379 		lo_gain += 0x26;
4380 
4381 	if (lo_gain >= 0x46) {
4382 		lo_gain -= 0x46;
4383 		ext_lna = 0x3000;
4384 	} else if (lo_gain >= 0x3a) {
4385 		lo_gain -= 0x3a;
4386 		ext_lna = 0x1000;
4387 	} else if (lo_gain >= 0x2e) {
4388 		lo_gain -= 0x2e;
4389 		ext_lna = 0x2000;
4390 	} else {
4391 		lo_gain -= 0x10;
4392 		ext_lna = 0;
4393 	}
4394 
4395 	for (loop = 0; loop < 16; ++loop) {
4396 		lo_gain -= (6 * loop);
4397 		if (lo_gain < 6)
4398 			break;
4399 	}
4400 
4401 	if (phy->phy_rev >= 7 && (sc->sc_card_flags & BWI_CARD_F_EXT_LNA)) {
4402 		if (ext_lna)
4403 			ext_lna |= 0x8000;
4404 		ext_lna |= (loop << 8);
4405 		switch (lpd) {
4406 		case 0x011:
4407 			return (0x8f92);
4408 		case 0x001:
4409 			return (0x8092 | ext_lna);
4410 		case 0x101:
4411 			return (0x2092 | ext_lna);
4412 		case 0x100:
4413 			return (0x2093 | ext_lna);
4414 		default:
4415 			panic("unsupported lpd\n");
4416 		}
4417 	} else {
4418 		ext_lna |= (loop << 8);
4419 		switch (lpd) {
4420 		case 0x011:
4421 			return (0xf92);
4422 		case 0x001:
4423 		case 0x101:
4424 			return (0x92 | ext_lna);
4425 		case 0x100:
4426 			return (0x93 | ext_lna);
4427 		default:
4428 			panic("unsupported lpd\n");
4429 		}
4430 	}
4431 
4432 	panic("never reached\n");
4433 	return (0);
4434 }
4435 
4436 static void
4437 bwi_rf_init_bcm2050(struct bwi_mac *mac)
4438 {
4439 #define SAVE_RF_MAX		3
4440 #define SAVE_PHY_COMM_MAX	4
4441 #define SAVE_PHY_11G_MAX	6
4442 	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
4443 	    { 0x0043, 0x0051, 0x0052 };
4444 	static const uint16_t save_phy_regs_comm[SAVE_PHY_COMM_MAX] =
4445 	    { 0x0015, 0x005a, 0x0059, 0x0058 };
4446 	static const uint16_t save_phy_regs_11g[SAVE_PHY_11G_MAX] =
4447 	    { 0x0811, 0x0812, 0x0814, 0x0815, 0x0429, 0x0802 };
4448 
4449 	uint16_t save_rf[SAVE_RF_MAX];
4450 	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
4451 	uint16_t save_phy_11g[SAVE_PHY_11G_MAX];
4452 	uint16_t phyr_35, phyr_30 = 0, rfr_78, phyr_80f = 0, phyr_810 = 0;
4453 	uint16_t bphy_ctrl = 0, bbp_atten, rf_chan_ex;
4454 	uint16_t phy812_val;
4455 	uint16_t calib;
4456 	uint32_t test_lim, test;
4457 	struct bwi_softc *sc = mac->mac_sc;
4458 	struct bwi_phy *phy = &mac->mac_phy;
4459 	struct bwi_rf *rf = &mac->mac_rf;
4460 	int i;
4461 
4462 	/*
4463 	 * Save registers for later restoring
4464 	 */
4465 	for (i = 0; i < SAVE_RF_MAX; ++i)
4466 		save_rf[i] = RF_READ(mac, save_rf_regs[i]);
4467 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
4468 		save_phy_comm[i] = PHY_READ(mac, save_phy_regs_comm[i]);
4469 
4470 	if (phy->phy_mode == IEEE80211_MODE_11B) {
4471 		phyr_30 = PHY_READ(mac, 0x30);
4472 		bphy_ctrl = CSR_READ_2(sc, BWI_BPHY_CTRL);
4473 
4474 		PHY_WRITE(mac, 0x30, 0xff);
4475 		CSR_WRITE_2(sc, BWI_BPHY_CTRL, 0x3f3f);
4476 	} else if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
4477 		for (i = 0; i < SAVE_PHY_11G_MAX; ++i) {
4478 			save_phy_11g[i] = PHY_READ(mac, save_phy_regs_11g[i]);
4479 		}
4480 
4481 		PHY_SETBITS(mac, 0x814, 0x3);
4482 		PHY_CLRBITS(mac, 0x815, 0x3);
4483 		PHY_CLRBITS(mac, 0x429, 0x8000);
4484 		PHY_CLRBITS(mac, 0x802, 0x3);
4485 
4486 		phyr_80f = PHY_READ(mac, 0x80f);
4487 		phyr_810 = PHY_READ(mac, 0x810);
4488 
4489 		if (phy->phy_rev >= 3)
4490 			PHY_WRITE(mac, 0x80f, 0xc020);
4491 		else
4492 			PHY_WRITE(mac, 0x80f, 0x8020);
4493 		PHY_WRITE(mac, 0x810, 0);
4494 
4495 		phy812_val = bwi_phy812_value(mac, 0x011);
4496 		PHY_WRITE(mac, 0x812, phy812_val);
4497 		if (phy->phy_rev < 7 ||
4498 		    (sc->sc_card_flags & BWI_CARD_F_EXT_LNA) == 0)
4499 			PHY_WRITE(mac, 0x811, 0x1b3);
4500 		else
4501 			PHY_WRITE(mac, 0x811, 0x9b3);
4502 	}
4503 	CSR_SETBITS_2(sc, BWI_RF_ANTDIV, 0x8000);
4504 
4505 	phyr_35 = PHY_READ(mac, 0x35);
4506 	PHY_CLRBITS(mac, 0x35, 0x80);
4507 
4508 	bbp_atten = CSR_READ_2(sc, BWI_BBP_ATTEN);
4509 	rf_chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX);
4510 
4511 	if (phy->phy_version == 0) {
4512 		CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0x122);
4513 	} else {
4514 		if (phy->phy_version >= 2)
4515 			PHY_FILT_SETBITS(mac, 0x3, 0xffbf, 0x40);
4516 		CSR_SETBITS_2(sc, BWI_RF_CHAN_EX, 0x2000);
4517 	}
4518 
4519 	calib = bwi_rf_calibval(mac);
4520 
4521 	if (phy->phy_mode == IEEE80211_MODE_11B)
4522 		RF_WRITE(mac, 0x78, 0x26);
4523 
4524 	if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
4525 		phy812_val = bwi_phy812_value(mac, 0x011);
4526 		PHY_WRITE(mac, 0x812, phy812_val);
4527 	}
4528 
4529 	PHY_WRITE(mac, 0x15, 0xbfaf);
4530 	PHY_WRITE(mac, 0x2b, 0x1403);
4531 
4532 	if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
4533 		phy812_val = bwi_phy812_value(mac, 0x001);
4534 		PHY_WRITE(mac, 0x812, phy812_val);
4535 	}
4536 
4537 	PHY_WRITE(mac, 0x15, 0xbfa0);
4538 
4539 	RF_SETBITS(mac, 0x51, 0x4);
4540 	if (rf->rf_rev == 8)
4541 		RF_WRITE(mac, 0x43, 0x1f);
4542 	else {
4543 		RF_WRITE(mac, 0x52, 0);
4544 		RF_FILT_SETBITS(mac, 0x43, 0xfff0, 0x9);
4545 	}
4546 
4547 	test_lim = 0;
4548 	PHY_WRITE(mac, 0x58, 0);
4549 	for (i = 0; i < 16; ++i) {
4550 		PHY_WRITE(mac, 0x5a, 0x480);
4551 		PHY_WRITE(mac, 0x59, 0xc810);
4552 
4553 		PHY_WRITE(mac, 0x58, 0xd);
4554 		if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
4555 			phy812_val = bwi_phy812_value(mac, 0x101);
4556 			PHY_WRITE(mac, 0x812, phy812_val);
4557 		}
4558 		PHY_WRITE(mac, 0x15, 0xafb0);
4559 		DELAY(10);
4560 
4561 		if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
4562 			phy812_val = bwi_phy812_value(mac, 0x101);
4563 			PHY_WRITE(mac, 0x812, phy812_val);
4564 		}
4565 		PHY_WRITE(mac, 0x15, 0xefb0);
4566 		DELAY(10);
4567 
4568 		if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
4569 			phy812_val = bwi_phy812_value(mac, 0x100);
4570 			PHY_WRITE(mac, 0x812, phy812_val);
4571 		}
4572 		PHY_WRITE(mac, 0x15, 0xfff0);
4573 		DELAY(20);
4574 
4575 		test_lim += PHY_READ(mac, 0x2d);
4576 
4577 		PHY_WRITE(mac, 0x58, 0);
4578 		if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
4579 			phy812_val = bwi_phy812_value(mac, 0x101);
4580 			PHY_WRITE(mac, 0x812, phy812_val);
4581 		}
4582 		PHY_WRITE(mac, 0x15, 0xafb0);
4583 	}
4584 	++test_lim;
4585 	test_lim >>= 9;
4586 
4587 	DELAY(10);
4588 
4589 	test = 0;
4590 	PHY_WRITE(mac, 0x58, 0);
4591 	for (i = 0; i < 16; ++i) {
4592 		int j;
4593 
4594 		rfr_78 = (bwi_bitswap4(i) << 1) | 0x20;
4595 		RF_WRITE(mac, 0x78, rfr_78);
4596 		DELAY(10);
4597 
4598 		/* NB: This block is slight different than the above one */
4599 		for (j = 0; j < 16; ++j) {
4600 			PHY_WRITE(mac, 0x5a, 0xd80);
4601 			PHY_WRITE(mac, 0x59, 0xc810);
4602 
4603 			PHY_WRITE(mac, 0x58, 0xd);
4604 			if ((phy->phy_flags & BWI_PHY_F_LINKED) ||
4605 			    phy->phy_rev >= 2) {
4606 				phy812_val = bwi_phy812_value(mac, 0x101);
4607 				PHY_WRITE(mac, 0x812, phy812_val);
4608 			}
4609 			PHY_WRITE(mac, 0x15, 0xafb0);
4610 			DELAY(10);
4611 
4612 			if ((phy->phy_flags & BWI_PHY_F_LINKED) ||
4613 			    phy->phy_rev >= 2) {
4614 				phy812_val = bwi_phy812_value(mac, 0x101);
4615 				PHY_WRITE(mac, 0x812, phy812_val);
4616 			}
4617 			PHY_WRITE(mac, 0x15, 0xefb0);
4618 			DELAY(10);
4619 
4620 			if ((phy->phy_flags & BWI_PHY_F_LINKED) ||
4621 			    phy->phy_rev >= 2) {
4622 				phy812_val = bwi_phy812_value(mac, 0x100);
4623 				PHY_WRITE(mac, 0x812, phy812_val);
4624 			}
4625 			PHY_WRITE(mac, 0x15, 0xfff0);
4626 			DELAY(10);
4627 
4628 			test += PHY_READ(mac, 0x2d);
4629 
4630 			PHY_WRITE(mac, 0x58, 0);
4631 			if ((phy->phy_flags & BWI_PHY_F_LINKED) ||
4632 			    phy->phy_rev >= 2) {
4633 				phy812_val = bwi_phy812_value(mac, 0x101);
4634 				PHY_WRITE(mac, 0x812, phy812_val);
4635 			}
4636 			PHY_WRITE(mac, 0x15, 0xafb0);
4637 		}
4638 
4639 		++test;
4640 		test >>= 8;
4641 
4642 		if (test > test_lim)
4643 			break;
4644 	}
4645 	if (i > 15)
4646 		rf->rf_calib = rfr_78;
4647 	else
4648 		rf->rf_calib = calib;
4649 	if (rf->rf_calib != 0xffff) {
4650 		DPRINTF(sc, BWI_DBG_RF | BWI_DBG_INIT,
4651 		    "RF calibration value: 0x%04x\n", rf->rf_calib);
4652 		rf->rf_flags |= BWI_RF_F_INITED;
4653 	}
4654 
4655 	/*
4656 	 * Restore trashes registers
4657 	 */
4658 	PHY_WRITE(mac, save_phy_regs_comm[0], save_phy_comm[0]);
4659 
4660 	for (i = 0; i < SAVE_RF_MAX; ++i) {
4661 		int pos = (i + 1) % SAVE_RF_MAX;
4662 
4663 		RF_WRITE(mac, save_rf_regs[pos], save_rf[pos]);
4664 	}
4665 	for (i = 1; i < SAVE_PHY_COMM_MAX; ++i)
4666 		PHY_WRITE(mac, save_phy_regs_comm[i], save_phy_comm[i]);
4667 
4668 	CSR_WRITE_2(sc, BWI_BBP_ATTEN, bbp_atten);
4669 	if (phy->phy_version != 0)
4670 		CSR_WRITE_2(sc, BWI_RF_CHAN_EX, rf_chan_ex);
4671 
4672 	PHY_WRITE(mac, 0x35, phyr_35);
4673 	bwi_rf_workaround(mac, rf->rf_curchan);
4674 
4675 	if (phy->phy_mode == IEEE80211_MODE_11B) {
4676 		PHY_WRITE(mac, 0x30, phyr_30);
4677 		CSR_WRITE_2(sc, BWI_BPHY_CTRL, bphy_ctrl);
4678 	} else if ((phy->phy_flags & BWI_PHY_F_LINKED) || phy->phy_rev >= 2) {
4679 		/* XXX Spec only says when PHY is linked (gmode) */
4680 		CSR_CLRBITS_2(sc, BWI_RF_ANTDIV, 0x8000);
4681 
4682 		for (i = 0; i < SAVE_PHY_11G_MAX; ++i) {
4683 			PHY_WRITE(mac, save_phy_regs_11g[i],
4684 			    save_phy_11g[i]);
4685 		}
4686 
4687 		PHY_WRITE(mac, 0x80f, phyr_80f);
4688 		PHY_WRITE(mac, 0x810, phyr_810);
4689 	}
4690 
4691 #undef SAVE_PHY_11G_MAX
4692 #undef SAVE_PHY_COMM_MAX
4693 #undef SAVE_RF_MAX
4694 }
4695 
4696 static uint16_t
4697 bwi_rf_calibval(struct bwi_mac *mac)
4698 {
4699 	/* http://bcm-specs.sipsolutions.net/RCCTable */
4700 	static const uint16_t rf_calibvals[] = {
4701 	    0x2, 0x3, 0x1, 0xf, 0x6, 0x7, 0x5, 0xf,
4702 	    0xa, 0xb, 0x9, 0xf, 0xe, 0xf, 0xd, 0xf
4703 	};
4704 
4705 	uint16_t val, calib;
4706 	int idx;
4707 
4708 	val = RF_READ(mac, BWI_RFR_BBP_ATTEN);
4709 	idx = __SHIFTOUT(val, BWI_RFR_BBP_ATTEN_CALIB_IDX);
4710 	KASSERT(idx < (int)(sizeof(rf_calibvals) / sizeof(rf_calibvals[0])));
4711 
4712 	calib = rf_calibvals[idx] << 1;
4713 	if (val & BWI_RFR_BBP_ATTEN_CALIB_BIT)
4714 		calib |= 0x1;
4715 	calib |= 0x20;
4716 
4717 	return (calib);
4718 }
4719 
4720 static int32_t
4721 _bwi_adjust_devide(int32_t num, int32_t den)
4722 {
4723 	if (num < 0)
4724 		return (num / den);
4725 	else
4726 		return ((num + den / 2) / den);
4727 }
4728 
4729 /*
4730  * http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table
4731  * "calculating table entries"
4732  */
4733 static int
4734 bwi_rf_calc_txpower(int8_t *txpwr, uint8_t idx, const int16_t pa_params[])
4735 {
4736 	int32_t m1, m2, f, dbm;
4737 	int i;
4738 
4739 	m1 = _bwi_adjust_devide(16 * pa_params[0] + idx * pa_params[1], 32);
4740 	m2 = imax(_bwi_adjust_devide(32768 + idx * pa_params[2], 256), 1);
4741 
4742 #define ITER_MAX	16
4743 	f = 256;
4744 	for (i = 0; i < ITER_MAX; ++i) {
4745 		int32_t q, d;
4746 
4747 		q = _bwi_adjust_devide(
4748 		    f * 4096 - _bwi_adjust_devide(m2 * f, 16) * f, 2048);
4749 		d = abs(q - f);
4750 		f = q;
4751 
4752 		if (d < 2)
4753 			break;
4754 	}
4755 	if (i == ITER_MAX)
4756 		return (EINVAL);
4757 #undef ITER_MAX
4758 
4759 	dbm = _bwi_adjust_devide(m1 * f, 8192);
4760 	if (dbm < -127)
4761 		dbm = -127;
4762 	else if (dbm > 128)
4763 		dbm = 128;
4764 
4765 	*txpwr = dbm;
4766 
4767 	return (0);
4768 }
4769 
4770 static int
4771 bwi_rf_map_txpower(struct bwi_mac *mac)
4772 {
4773 	struct bwi_softc *sc = mac->mac_sc;
4774 	struct bwi_rf *rf = &mac->mac_rf;
4775 	struct bwi_phy *phy = &mac->mac_phy;
4776 	uint16_t sprom_ofs, val, mask;
4777 	int16_t pa_params[3];
4778 	int error = 0, i, ant_gain, reg_txpower_max;
4779 #ifdef BWI_DEBUG
4780 	int debug = sc->sc_debug &
4781 	    (BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH);
4782 #endif
4783 
4784 	/*
4785 	 * Find out max TX power
4786 	 */
4787 	val = bwi_read_sprom(sc, BWI_SPROM_MAX_TXPWR);
4788 	if (phy->phy_mode == IEEE80211_MODE_11A) {
4789 		rf->rf_txpower_max = __SHIFTOUT(val,
4790 		    BWI_SPROM_MAX_TXPWR_MASK_11A);
4791 	} else {
4792 		rf->rf_txpower_max = __SHIFTOUT(val,
4793 		    BWI_SPROM_MAX_TXPWR_MASK_11BG);
4794 
4795 		if ((sc->sc_card_flags & BWI_CARD_F_PA_GPIO9) &&
4796 		    phy->phy_mode == IEEE80211_MODE_11G)
4797 			rf->rf_txpower_max -= 3;
4798 	}
4799 	if (rf->rf_txpower_max <= 0) {
4800 		aprint_error_dev(sc->sc_dev,
4801 		    "invalid max txpower in sprom\n");
4802 		rf->rf_txpower_max = 74;
4803 	}
4804 	DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH,
4805 	    "max txpower from sprom: %d dBm\n", rf->rf_txpower_max);
4806 
4807 	/*
4808 	 * Find out region/domain max TX power, which is adjusted
4809 	 * by antenna gain and 1.5 dBm fluctuation as mentioned
4810 	 * in v3 spec.
4811 	 */
4812 	val = bwi_read_sprom(sc, BWI_SPROM_ANT_GAIN);
4813 	if (phy->phy_mode == IEEE80211_MODE_11A)
4814 		ant_gain = __SHIFTOUT(val, BWI_SPROM_ANT_GAIN_MASK_11A);
4815 	else
4816 		ant_gain = __SHIFTOUT(val, BWI_SPROM_ANT_GAIN_MASK_11BG);
4817 	if (ant_gain == 0xff) {
4818 		/* XXX why this always invalid? */
4819 		aprint_error_dev(sc->sc_dev,
4820 		    "invalid antenna gain in sprom\n");
4821 		ant_gain = 2;
4822 	}
4823 	ant_gain *= 4;
4824 	DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH,
4825 	    "ant gain %d dBm\n", ant_gain);
4826 
4827 	reg_txpower_max = 90 - ant_gain - 6;	/* XXX magic number */
4828 	DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH,
4829 	    "region/domain max txpower %d dBm\n", reg_txpower_max);
4830 
4831 	/*
4832 	 * Force max TX power within region/domain TX power limit
4833 	 */
4834 	if (rf->rf_txpower_max > reg_txpower_max)
4835 		rf->rf_txpower_max = reg_txpower_max;
4836 	DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH,
4837 	    "max txpower %d dBm\n", rf->rf_txpower_max);
4838 
4839 	/*
4840 	 * Create TSSI to TX power mapping
4841 	 */
4842 
4843 	if (sc->sc_bbp_id == BWI_BBPID_BCM4301 &&
4844 	    rf->rf_type != BWI_RF_T_BCM2050) {
4845 		rf->rf_idle_tssi0 = BWI_DEFAULT_IDLE_TSSI;
4846 		memcpy(rf->rf_txpower_map0, bwi_txpower_map_11b,
4847 		      sizeof(rf->rf_txpower_map0));
4848 		goto back;
4849 	}
4850 
4851 #define IS_VALID_PA_PARAM(p)	((p) != 0 && (p) != -1)
4852 	/*
4853 	 * Extract PA parameters
4854 	 */
4855 	if (phy->phy_mode == IEEE80211_MODE_11A)
4856 		sprom_ofs = BWI_SPROM_PA_PARAM_11A;
4857 	else
4858 		sprom_ofs = BWI_SPROM_PA_PARAM_11BG;
4859 	for (i = 0; i < __arraycount(pa_params); ++i)
4860 		pa_params[i] = (int16_t)bwi_read_sprom(sc, sprom_ofs + (i * 2));
4861 
4862 	for (i = 0; i < __arraycount(pa_params); ++i) {
4863 		/*
4864 		 * If one of the PA parameters from SPROM is not valid,
4865 		 * fall back to the default values, if there are any.
4866 		 */
4867 		if (!IS_VALID_PA_PARAM(pa_params[i])) {
4868 			const int8_t *txpower_map;
4869 
4870 			if (phy->phy_mode == IEEE80211_MODE_11A) {
4871 				aprint_error_dev(sc->sc_dev,
4872 				    "no tssi2dbm table for 11a PHY\n");
4873 				return (ENXIO);
4874 			}
4875 
4876 			if (phy->phy_mode == IEEE80211_MODE_11G) {
4877 				DPRINTF(sc,
4878 				    BWI_DBG_RF | BWI_DBG_TXPOWER |
4879 					BWI_DBG_ATTACH,
4880 				    "use default 11g TSSI map\n");
4881 				txpower_map = bwi_txpower_map_11g;
4882 			} else {
4883 				DPRINTF(sc,
4884 				    BWI_DBG_RF | BWI_DBG_TXPOWER |
4885 					BWI_DBG_ATTACH,
4886 				    "use default 11b TSSI map\n");
4887 				txpower_map = bwi_txpower_map_11b;
4888 			}
4889 
4890 			rf->rf_idle_tssi0 = BWI_DEFAULT_IDLE_TSSI;
4891 			memcpy(rf->rf_txpower_map0, txpower_map,
4892 			      sizeof(rf->rf_txpower_map0));
4893 			goto back;
4894 		}
4895 	}
4896 
4897 	/*
4898 	 * All of the PA parameters from SPROM are valid.
4899 	 */
4900 
4901 	/*
4902 	 * Extract idle TSSI from SPROM.
4903 	 */
4904 	val = bwi_read_sprom(sc, BWI_SPROM_IDLE_TSSI);
4905 	DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH,
4906 	    "sprom idle tssi: 0x%04x\n", val);
4907 
4908 	if (phy->phy_mode == IEEE80211_MODE_11A)
4909 		mask = BWI_SPROM_IDLE_TSSI_MASK_11A;
4910 	else
4911 		mask = BWI_SPROM_IDLE_TSSI_MASK_11BG;
4912 
4913 	rf->rf_idle_tssi0 = (int)__SHIFTOUT(val, mask);
4914 	if (!IS_VALID_PA_PARAM(rf->rf_idle_tssi0))
4915 		rf->rf_idle_tssi0 = 62;
4916 
4917 #undef IS_VALID_PA_PARAM
4918 
4919 	/*
4920 	 * Calculate TX power map, which is indexed by TSSI
4921 	 */
4922 	DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH,
4923 	    "TSSI-TX power map:\n");
4924 	for (i = 0; i < BWI_TSSI_MAX; ++i) {
4925 		error = bwi_rf_calc_txpower(&rf->rf_txpower_map0[i], i,
4926 					    pa_params);
4927 		if (error) {
4928 			aprint_error_dev(sc->sc_dev,
4929 			    "bwi_rf_calc_txpower failed\n");
4930 			break;
4931 		}
4932 #ifdef BWI_DEBUG
4933 		if (debug) {
4934 			if (i % 8 == 0) {
4935 				if (i != 0)
4936 					aprint_debug("\n");
4937 				aprint_debug_dev(sc->sc_dev, "");
4938 			}
4939 			aprint_debug(" %d", rf->rf_txpower_map0[i]);
4940 		}
4941 #endif
4942 	}
4943 #ifdef BWI_DEBUG
4944 	if (debug)
4945 		aprint_debug("\n");
4946 #endif
4947 back:
4948 	DPRINTF(sc, BWI_DBG_RF | BWI_DBG_TXPOWER | BWI_DBG_ATTACH,
4949 	    "idle tssi0: %d\n", rf->rf_idle_tssi0);
4950 
4951 	return (error);
4952 }
4953 
4954 static void
4955 bwi_rf_lo_update_11g(struct bwi_mac *mac)
4956 {
4957 	struct bwi_softc *sc = mac->mac_sc;
4958 	struct ifnet *ifp = &sc->sc_if;
4959 	struct bwi_rf *rf = &mac->mac_rf;
4960 	struct bwi_phy *phy = &mac->mac_phy;
4961 	struct bwi_tpctl *tpctl = &mac->mac_tpctl;
4962 	struct rf_saveregs regs;
4963 	uint16_t ant_div, chan_ex;
4964 	uint8_t devi_ctrl;
4965 	uint orig_chan;
4966 
4967 	DPRINTF(sc, BWI_DBG_RF | BWI_DBG_INIT, "%s enter\n", __func__);
4968 
4969 	/*
4970 	 * Save RF/PHY registers for later restoration
4971 	 */
4972 	orig_chan = rf->rf_curchan;
4973 	memset(&regs, 0, sizeof(regs));
4974 
4975 	if (phy->phy_flags & BWI_PHY_F_LINKED) {
4976 		SAVE_PHY_REG(mac, &regs, 429);
4977 		SAVE_PHY_REG(mac, &regs, 802);
4978 
4979 		PHY_WRITE(mac, 0x429, regs.phy_429 & 0x7fff);
4980 		PHY_WRITE(mac, 0x802, regs.phy_802 & 0xfffc);
4981 	}
4982 
4983 	ant_div = CSR_READ_2(sc, BWI_RF_ANTDIV);
4984 	CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div | 0x8000);
4985 	chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX);
4986 
4987 	SAVE_PHY_REG(mac, &regs, 15);
4988 	SAVE_PHY_REG(mac, &regs, 2a);
4989 	SAVE_PHY_REG(mac, &regs, 35);
4990 	SAVE_PHY_REG(mac, &regs, 60);
4991 	SAVE_RF_REG(mac, &regs, 43);
4992 	SAVE_RF_REG(mac, &regs, 7a);
4993 	SAVE_RF_REG(mac, &regs, 52);
4994 	if (phy->phy_flags & BWI_PHY_F_LINKED) {
4995 		SAVE_PHY_REG(mac, &regs, 811);
4996 		SAVE_PHY_REG(mac, &regs, 812);
4997 		SAVE_PHY_REG(mac, &regs, 814);
4998 		SAVE_PHY_REG(mac, &regs, 815);
4999 	}
5000 
5001 	/* Force to channel 6 */
5002 	bwi_rf_set_chan(mac, 6, 0);
5003 
5004 	if (phy->phy_flags & BWI_PHY_F_LINKED) {
5005 		PHY_WRITE(mac, 0x429, regs.phy_429 & 0x7fff);
5006 		PHY_WRITE(mac, 0x802, regs.phy_802 & 0xfffc);
5007 		bwi_mac_dummy_xmit(mac);
5008 	}
5009 	RF_WRITE(mac, 0x43, 0x6);
5010 
5011 	bwi_phy_set_bbp_atten(mac, 2);
5012 
5013 	CSR_WRITE_2(sc, BWI_RF_CHAN_EX, 0);
5014 
5015 	PHY_WRITE(mac, 0x2e, 0x7f);
5016 	PHY_WRITE(mac, 0x80f, 0x78);
5017 	PHY_WRITE(mac, 0x35, regs.phy_35 & 0xff7f);
5018 	RF_WRITE(mac, 0x7a, regs.rf_7a & 0xfff0);
5019 	PHY_WRITE(mac, 0x2b, 0x203);
5020 	PHY_WRITE(mac, 0x2a, 0x8a3);
5021 
5022 	if (phy->phy_flags & BWI_PHY_F_LINKED) {
5023 		PHY_WRITE(mac, 0x814, regs.phy_814 | 0x3);
5024 		PHY_WRITE(mac, 0x815, regs.phy_815 & 0xfffc);
5025 		PHY_WRITE(mac, 0x811, 0x1b3);
5026 		PHY_WRITE(mac, 0x812, 0xb2);
5027 	}
5028 
5029 	if ((ifp->if_flags & IFF_RUNNING) == 0)
5030 		tpctl->tp_ctrl2 = bwi_rf_get_tp_ctrl2(mac);
5031 	PHY_WRITE(mac, 0x80f, 0x8078);
5032 
5033 	/*
5034 	 * Measure all RF LO
5035 	 */
5036 	devi_ctrl = _bwi_rf_lo_update_11g(mac, regs.rf_7a);
5037 
5038 	/*
5039 	 * Restore saved RF/PHY registers
5040 	 */
5041 	if (phy->phy_flags & BWI_PHY_F_LINKED) {
5042 		PHY_WRITE(mac, 0x15, 0xe300);
5043 		PHY_WRITE(mac, 0x812, (devi_ctrl << 8) | 0xa0);
5044 		DELAY(5);
5045 		PHY_WRITE(mac, 0x812, (devi_ctrl << 8) | 0xa2);
5046 		DELAY(2);
5047 		PHY_WRITE(mac, 0x812, (devi_ctrl << 8) | 0xa3);
5048 	} else
5049 		PHY_WRITE(mac, 0x15, devi_ctrl | 0xefa0);
5050 
5051 	if ((ifp->if_flags & IFF_RUNNING) == 0)
5052 		tpctl = NULL;
5053 	bwi_rf_lo_adjust(mac, tpctl);
5054 
5055 	PHY_WRITE(mac, 0x2e, 0x807f);
5056 	if (phy->phy_flags & BWI_PHY_F_LINKED)
5057 		PHY_WRITE(mac, 0x2f, 0x202);
5058 	else
5059 		PHY_WRITE(mac, 0x2f, 0x101);
5060 
5061 	CSR_WRITE_2(sc, BWI_RF_CHAN_EX, chan_ex);
5062 
5063 	RESTORE_PHY_REG(mac, &regs, 15);
5064 	RESTORE_PHY_REG(mac, &regs, 2a);
5065 	RESTORE_PHY_REG(mac, &regs, 35);
5066 	RESTORE_PHY_REG(mac, &regs, 60);
5067 
5068 	RESTORE_RF_REG(mac, &regs, 43);
5069 	RESTORE_RF_REG(mac, &regs, 7a);
5070 
5071 	regs.rf_52 &= 0xf0;
5072 	regs.rf_52 |= (RF_READ(mac, 0x52) & 0xf);
5073 	RF_WRITE(mac, 0x52, regs.rf_52);
5074 
5075 	CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div);
5076 
5077 	if (phy->phy_flags & BWI_PHY_F_LINKED) {
5078 		RESTORE_PHY_REG(mac, &regs, 811);
5079 		RESTORE_PHY_REG(mac, &regs, 812);
5080 		RESTORE_PHY_REG(mac, &regs, 814);
5081 		RESTORE_PHY_REG(mac, &regs, 815);
5082 		RESTORE_PHY_REG(mac, &regs, 429);
5083 		RESTORE_PHY_REG(mac, &regs, 802);
5084 	}
5085 
5086 	bwi_rf_set_chan(mac, orig_chan, 1);
5087 }
5088 
5089 static uint32_t
5090 bwi_rf_lo_devi_measure(struct bwi_mac *mac, uint16_t ctrl)
5091 {
5092 	struct bwi_phy *phy = &mac->mac_phy;
5093 	uint32_t devi = 0;
5094 	int i;
5095 
5096 	if (phy->phy_flags & BWI_PHY_F_LINKED)
5097 		ctrl <<= 8;
5098 
5099 	for (i = 0; i < 8; ++i) {
5100 		if (phy->phy_flags & BWI_PHY_F_LINKED) {
5101 			PHY_WRITE(mac, 0x15, 0xe300);
5102 			PHY_WRITE(mac, 0x812, ctrl | 0xb0);
5103 			DELAY(5);
5104 			PHY_WRITE(mac, 0x812, ctrl | 0xb2);
5105 			DELAY(2);
5106 			PHY_WRITE(mac, 0x812, ctrl | 0xb3);
5107 			DELAY(4);
5108 			PHY_WRITE(mac, 0x15, 0xf300);
5109 		} else {
5110 			PHY_WRITE(mac, 0x15, ctrl | 0xefa0);
5111 			DELAY(2);
5112 			PHY_WRITE(mac, 0x15, ctrl | 0xefe0);
5113 			DELAY(4);
5114 			PHY_WRITE(mac, 0x15, ctrl | 0xffe0);
5115 		}
5116 		DELAY(8);
5117 		devi += PHY_READ(mac, 0x2d);
5118 	}
5119 
5120 	return (devi);
5121 }
5122 
5123 static uint16_t
5124 bwi_rf_get_tp_ctrl2(struct bwi_mac *mac)
5125 {
5126 	uint32_t devi_min;
5127 	uint16_t tp_ctrl2 = 0;
5128 	int i;
5129 
5130 	RF_WRITE(mac, 0x52, 0);
5131 	DELAY(10);
5132 	devi_min = bwi_rf_lo_devi_measure(mac, 0);
5133 
5134 	for (i = 0; i < 16; ++i) {
5135 		uint32_t devi;
5136 
5137 		RF_WRITE(mac, 0x52, i);
5138 		DELAY(10);
5139 		devi = bwi_rf_lo_devi_measure(mac, 0);
5140 
5141 		if (devi < devi_min) {
5142 			devi_min = devi;
5143 			tp_ctrl2 = i;
5144 		}
5145 	}
5146 
5147 	return (tp_ctrl2);
5148 }
5149 
5150 static uint8_t
5151 _bwi_rf_lo_update_11g(struct bwi_mac *mac, uint16_t orig_rf7a)
5152 {
5153 #define RF_ATTEN_LISTSZ	14
5154 #define BBP_ATTEN_MAX	4	/* half */
5155 	static const int rf_atten_list[RF_ATTEN_LISTSZ] =
5156 	    { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8, 1, 2, 3, 4 };
5157 	static const int rf_atten_init_list[RF_ATTEN_LISTSZ] =
5158             { 0, 3, 1, 5, 7, 3, 2, 0, 4, 6, -1, -1, -1, -1 };
5159 	static const int rf_lo_measure_order[RF_ATTEN_LISTSZ] =
5160 	    { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8, 10, 11, 12, 13 };
5161 
5162 	struct ifnet *ifp = &mac->mac_sc->sc_if;
5163 	struct bwi_rf_lo lo_save, *lo;
5164 	uint8_t devi_ctrl = 0;
5165 	int idx, adj_rf7a = 0;
5166 
5167 	memset(&lo_save, 0, sizeof(lo_save));
5168 	for (idx = 0; idx < RF_ATTEN_LISTSZ; ++idx) {
5169 		int init_rf_atten = rf_atten_init_list[idx];
5170 		int rf_atten = rf_atten_list[idx];
5171 		int bbp_atten;
5172 
5173 		for (bbp_atten = 0; bbp_atten < BBP_ATTEN_MAX; ++bbp_atten) {
5174 			uint16_t tp_ctrl2, rf7a;
5175 
5176 			if ((ifp->if_flags & IFF_RUNNING) == 0) {
5177 				if (idx == 0) {
5178 					memset(&lo_save, 0, sizeof(lo_save));
5179 				} else if (init_rf_atten < 0) {
5180 					lo = bwi_get_rf_lo(mac,
5181 					    rf_atten, 2 * bbp_atten);
5182 					memcpy(&lo_save, lo, sizeof(lo_save));
5183 				} else {
5184 					lo = bwi_get_rf_lo(mac,
5185 					    init_rf_atten, 0);
5186 					memcpy(&lo_save, lo, sizeof(lo_save));
5187 				}
5188 
5189 				devi_ctrl = 0;
5190 				adj_rf7a = 0;
5191 
5192 				/*
5193 				 * XXX
5194 				 * Linux driver overflows 'val'
5195 				 */
5196 				if (init_rf_atten >= 0) {
5197 					int val;
5198 
5199 					val = rf_atten * 2 + bbp_atten;
5200 					if (val > 14) {
5201 						adj_rf7a = 1;
5202 						if (val > 17)
5203 							devi_ctrl = 1;
5204 						if (val > 19)
5205 							devi_ctrl = 2;
5206 					}
5207 				}
5208 			} else {
5209 				lo = bwi_get_rf_lo(mac,
5210 					rf_atten, 2 * bbp_atten);
5211 				if (!bwi_rf_lo_isused(mac, lo))
5212 					continue;
5213 				memcpy(&lo_save, lo, sizeof(lo_save));
5214 
5215 				devi_ctrl = 3;
5216 				adj_rf7a = 0;
5217 			}
5218 
5219 			RF_WRITE(mac, BWI_RFR_ATTEN, rf_atten);
5220 
5221 			tp_ctrl2 = mac->mac_tpctl.tp_ctrl2;
5222 			if (init_rf_atten < 0)
5223 				tp_ctrl2 |= (3 << 4);
5224 			RF_WRITE(mac, BWI_RFR_TXPWR, tp_ctrl2);
5225 
5226 			DELAY(10);
5227 
5228 			bwi_phy_set_bbp_atten(mac, bbp_atten * 2);
5229 
5230 			rf7a = orig_rf7a & 0xfff0;
5231 			if (adj_rf7a)
5232 				rf7a |= 0x8;
5233 			RF_WRITE(mac, 0x7a, rf7a);
5234 
5235 			lo = bwi_get_rf_lo(mac,
5236 				rf_lo_measure_order[idx], bbp_atten * 2);
5237 			bwi_rf_lo_measure_11g(mac, &lo_save, lo, devi_ctrl);
5238 		}
5239 	}
5240 
5241 	return (devi_ctrl);
5242 
5243 #undef RF_ATTEN_LISTSZ
5244 #undef BBP_ATTEN_MAX
5245 }
5246 
5247 static void
5248 bwi_rf_lo_measure_11g(struct bwi_mac *mac, const struct bwi_rf_lo *src_lo,
5249     struct bwi_rf_lo *dst_lo, uint8_t devi_ctrl)
5250 {
5251 #define LO_ADJUST_MIN	1
5252 #define LO_ADJUST_MAX	8
5253 #define LO_ADJUST(hi, lo)	{ .ctrl_hi = hi, .ctrl_lo = lo }
5254 	static const struct bwi_rf_lo rf_lo_adjust[LO_ADJUST_MAX] = {
5255 		LO_ADJUST(1,	1),
5256 		LO_ADJUST(1,	0),
5257 		LO_ADJUST(1,	-1),
5258 		LO_ADJUST(0,	-1),
5259 		LO_ADJUST(-1,	-1),
5260 		LO_ADJUST(-1,	0),
5261 		LO_ADJUST(-1,	1),
5262 		LO_ADJUST(0,	1)
5263 	};
5264 #undef LO_ADJUST
5265 
5266 	struct bwi_rf_lo lo_min;
5267 	uint32_t devi_min;
5268 	int found, loop_count, adjust_state;
5269 
5270 	memcpy(&lo_min, src_lo, sizeof(lo_min));
5271 	RF_LO_WRITE(mac, &lo_min);
5272 	devi_min = bwi_rf_lo_devi_measure(mac, devi_ctrl);
5273 
5274 	loop_count = 12;	/* XXX */
5275 	adjust_state = 0;
5276 	do {
5277 		struct bwi_rf_lo lo_base;
5278 		int i, fin;
5279 
5280 		found = 0;
5281 		if (adjust_state == 0) {
5282 			i = LO_ADJUST_MIN;
5283 			fin = LO_ADJUST_MAX;
5284 		} else if (adjust_state % 2 == 0) {
5285 			i = adjust_state - 1;
5286 			fin = adjust_state + 1;
5287 		} else {
5288 			i = adjust_state - 2;
5289 			fin = adjust_state + 2;
5290 		}
5291 
5292 		if (i < LO_ADJUST_MIN)
5293 			i += LO_ADJUST_MAX;
5294 		KASSERT(i <= LO_ADJUST_MAX && i >= LO_ADJUST_MIN);
5295 
5296 		if (fin > LO_ADJUST_MAX)
5297 			fin -= LO_ADJUST_MAX;
5298 		KASSERT(fin <= LO_ADJUST_MAX && fin >= LO_ADJUST_MIN);
5299 
5300 		memcpy(&lo_base, &lo_min, sizeof(lo_base));
5301 		for (;;) {
5302 			struct bwi_rf_lo lo;
5303 
5304 			lo.ctrl_hi = lo_base.ctrl_hi +
5305 				rf_lo_adjust[i - 1].ctrl_hi;
5306 			lo.ctrl_lo = lo_base.ctrl_lo +
5307 				rf_lo_adjust[i - 1].ctrl_lo;
5308 
5309 			if (abs(lo.ctrl_lo) < 9 && abs(lo.ctrl_hi) < 9) {
5310 				uint32_t devi;
5311 
5312 				RF_LO_WRITE(mac, &lo);
5313 				devi = bwi_rf_lo_devi_measure(mac, devi_ctrl);
5314 				if (devi < devi_min) {
5315 					devi_min = devi;
5316 					adjust_state = i;
5317 					found = 1;
5318 					memcpy(&lo_min, &lo, sizeof(lo_min));
5319 				}
5320 			}
5321 			if (i == fin)
5322 				break;
5323 			if (i == LO_ADJUST_MAX)
5324 				i = LO_ADJUST_MIN;
5325 			else
5326 				++i;
5327 		}
5328 	} while (loop_count-- && found);
5329 
5330 	memcpy(dst_lo, &lo_min, sizeof(*dst_lo));
5331 
5332 #undef LO_ADJUST_MIN
5333 #undef LO_ADJUST_MAX
5334 }
5335 
5336 static void
5337 bwi_rf_calc_nrssi_slope_11b(struct bwi_mac *mac)
5338 {
5339 #define SAVE_RF_MAX	3
5340 #define SAVE_PHY_MAX	8
5341 	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
5342 	    { 0x7a, 0x52, 0x43 };
5343 	static const uint16_t save_phy_regs[SAVE_PHY_MAX] =
5344 	    { 0x30, 0x26, 0x15, 0x2a, 0x20, 0x5a, 0x59, 0x58 };
5345 
5346 	struct bwi_softc *sc = mac->mac_sc;
5347 	struct bwi_rf *rf = &mac->mac_rf;
5348 	struct bwi_phy *phy = &mac->mac_phy;
5349 	uint16_t save_rf[SAVE_RF_MAX];
5350 	uint16_t save_phy[SAVE_PHY_MAX];
5351 	uint16_t ant_div, chan_ex;
5352 	int16_t nrssi[2];
5353 	int i;
5354 
5355 	/*
5356 	 * Save RF/PHY registers for later restoration
5357 	 */
5358 	for (i = 0; i < SAVE_RF_MAX; ++i)
5359 		save_rf[i] = RF_READ(mac, save_rf_regs[i]);
5360 	for (i = 0; i < SAVE_PHY_MAX; ++i)
5361 		save_phy[i] = PHY_READ(mac, save_phy_regs[i]);
5362 
5363 	ant_div = CSR_READ_2(sc, BWI_RF_ANTDIV);
5364 	(void)CSR_READ_2(sc, BWI_BBP_ATTEN);
5365 	chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX);
5366 
5367 	/*
5368 	 * Calculate nrssi0
5369 	 */
5370 	if (phy->phy_rev >= 5)
5371 		RF_CLRBITS(mac, 0x7a, 0xff80);
5372 	else
5373 		RF_CLRBITS(mac, 0x7a, 0xfff0);
5374 	PHY_WRITE(mac, 0x30, 0xff);
5375 
5376 	CSR_WRITE_2(sc, BWI_BPHY_CTRL, 0x7f7f);
5377 
5378 	PHY_WRITE(mac, 0x26, 0);
5379 	PHY_SETBITS(mac, 0x15, 0x20);
5380 	PHY_WRITE(mac, 0x2a, 0x8a3);
5381 	RF_SETBITS(mac, 0x7a, 0x80);
5382 
5383 	nrssi[0] = (int16_t)PHY_READ(mac, 0x27);
5384 
5385 	/*
5386 	 * Calculate nrssi1
5387 	 */
5388 	RF_CLRBITS(mac, 0x7a, 0xff80);
5389 	if (phy->phy_version >= 2)
5390 		CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0x40);
5391 	else if (phy->phy_version == 0)
5392 		CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0x122);
5393 	else
5394 		CSR_CLRBITS_2(sc, BWI_RF_CHAN_EX, 0xdfff);
5395 
5396 	PHY_WRITE(mac, 0x20, 0x3f3f);
5397 	PHY_WRITE(mac, 0x15, 0xf330);
5398 
5399 	RF_WRITE(mac, 0x5a, 0x60);
5400 	RF_CLRBITS(mac, 0x43, 0xff0f);
5401 
5402 	PHY_WRITE(mac, 0x5a, 0x480);
5403 	PHY_WRITE(mac, 0x59, 0x810);
5404 	PHY_WRITE(mac, 0x58, 0xd);
5405 
5406 	DELAY(20);
5407 
5408 	nrssi[1] = (int16_t)PHY_READ(mac, 0x27);
5409 
5410 	/*
5411 	 * Restore saved RF/PHY registers
5412 	 */
5413 	PHY_WRITE(mac, save_phy_regs[0], save_phy[0]);
5414 	RF_WRITE(mac, save_rf_regs[0], save_rf[0]);
5415 
5416 	CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div);
5417 
5418 	for (i = 1; i < 4; ++i)
5419 		PHY_WRITE(mac, save_phy_regs[i], save_phy[i]);
5420 
5421 	bwi_rf_workaround(mac, rf->rf_curchan);
5422 
5423 	if (phy->phy_version != 0)
5424 		CSR_WRITE_2(sc, BWI_RF_CHAN_EX, chan_ex);
5425 
5426 	for (; i < SAVE_PHY_MAX; ++i)
5427 		PHY_WRITE(mac, save_phy_regs[i], save_phy[i]);
5428 
5429 	for (i = 1; i < SAVE_RF_MAX; ++i)
5430 		RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
5431 
5432 	/*
5433 	 * Install calculated narrow RSSI values
5434 	 */
5435 	if (nrssi[0] == nrssi[1])
5436 		rf->rf_nrssi_slope = 0x10000;
5437 	else
5438 		rf->rf_nrssi_slope = 0x400000 / (nrssi[0] - nrssi[1]);
5439 	if (nrssi[0] <= -4) {
5440 		rf->rf_nrssi[0] = nrssi[0];
5441 		rf->rf_nrssi[1] = nrssi[1];
5442 	}
5443 
5444 #undef SAVE_RF_MAX
5445 #undef SAVE_PHY_MAX
5446 }
5447 
5448 static void
5449 bwi_rf_set_nrssi_ofs_11g(struct bwi_mac *mac)
5450 {
5451 #define SAVE_RF_MAX		2
5452 #define SAVE_PHY_COMM_MAX	10
5453 #define SAVE_PHY6_MAX		8
5454 	static const uint16_t save_rf_regs[SAVE_RF_MAX] = { 0x7a, 0x43 };
5455 	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] = {
5456 		0x0001, 0x0811, 0x0812, 0x0814,
5457 		0x0815, 0x005a, 0x0059, 0x0058,
5458 		0x000a, 0x0003
5459 	};
5460 	static const uint16_t save_phy6_regs[SAVE_PHY6_MAX] = {
5461 		0x002e, 0x002f, 0x080f, 0x0810,
5462 		0x0801, 0x0060, 0x0014, 0x0478
5463 	};
5464 
5465 	struct bwi_phy *phy = &mac->mac_phy;
5466 	uint16_t save_rf[SAVE_RF_MAX];
5467 	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
5468 	uint16_t save_phy6[SAVE_PHY6_MAX];
5469 	uint16_t rf7b = 0xffff;
5470 	int16_t nrssi;
5471 	int i, phy6_idx = 0;
5472 
5473 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
5474 		save_phy_comm[i] = PHY_READ(mac, save_phy_comm_regs[i]);
5475 	for (i = 0; i < SAVE_RF_MAX; ++i)
5476 		save_rf[i] = RF_READ(mac, save_rf_regs[i]);
5477 
5478 	PHY_CLRBITS(mac, 0x429, 0x8000);
5479 	PHY_FILT_SETBITS(mac, 0x1, 0x3fff, 0x4000);
5480 	PHY_SETBITS(mac, 0x811, 0xc);
5481 	PHY_FILT_SETBITS(mac, 0x812, 0xfff3, 0x4);
5482 	PHY_CLRBITS(mac, 0x802, 0x3);
5483 
5484 	if (phy->phy_rev >= 6) {
5485 		for (i = 0; i < SAVE_PHY6_MAX; ++i)
5486 			save_phy6[i] = PHY_READ(mac, save_phy6_regs[i]);
5487 
5488 		PHY_WRITE(mac, 0x2e, 0);
5489 		PHY_WRITE(mac, 0x2f, 0);
5490 		PHY_WRITE(mac, 0x80f, 0);
5491 		PHY_WRITE(mac, 0x810, 0);
5492 		PHY_SETBITS(mac, 0x478, 0x100);
5493 		PHY_SETBITS(mac, 0x801, 0x40);
5494 		PHY_SETBITS(mac, 0x60, 0x40);
5495 		PHY_SETBITS(mac, 0x14, 0x200);
5496 	}
5497 
5498 	RF_SETBITS(mac, 0x7a, 0x70);
5499 	RF_SETBITS(mac, 0x7a, 0x80);
5500 
5501 	DELAY(30);
5502 
5503 	nrssi = bwi_nrssi_11g(mac);
5504 	if (nrssi == 31) {
5505 		for (i = 7; i >= 4; --i) {
5506 			RF_WRITE(mac, 0x7b, i);
5507 			DELAY(20);
5508 			nrssi = bwi_nrssi_11g(mac);
5509 			if (nrssi < 31 && rf7b == 0xffff)
5510 				rf7b = i;
5511 		}
5512 		if (rf7b == 0xffff)
5513 			rf7b = 4;
5514 	} else {
5515 		struct bwi_gains gains;
5516 
5517 		RF_CLRBITS(mac, 0x7a, 0xff80);
5518 
5519 		PHY_SETBITS(mac, 0x814, 0x1);
5520 		PHY_CLRBITS(mac, 0x815, 0x1);
5521 		PHY_SETBITS(mac, 0x811, 0xc);
5522 		PHY_SETBITS(mac, 0x812, 0xc);
5523 		PHY_SETBITS(mac, 0x811, 0x30);
5524 		PHY_SETBITS(mac, 0x812, 0x30);
5525 		PHY_WRITE(mac, 0x5a, 0x480);
5526 		PHY_WRITE(mac, 0x59, 0x810);
5527 		PHY_WRITE(mac, 0x58, 0xd);
5528 		if (phy->phy_version == 0)
5529 			PHY_WRITE(mac, 0x3, 0x122);
5530 		else
5531 			PHY_SETBITS(mac, 0xa, 0x2000);
5532 		PHY_SETBITS(mac, 0x814, 0x4);
5533 		PHY_CLRBITS(mac, 0x815, 0x4);
5534 		PHY_FILT_SETBITS(mac, 0x3, 0xff9f, 0x40);
5535 		RF_SETBITS(mac, 0x7a, 0xf);
5536 
5537 		memset(&gains, 0, sizeof(gains));
5538 		gains.tbl_gain1 = 3;
5539 		gains.tbl_gain2 = 0;
5540 		gains.phy_gain = 1;
5541 		bwi_set_gains(mac, &gains);
5542 
5543 		RF_FILT_SETBITS(mac, 0x43, 0xf0, 0xf);
5544 		DELAY(30);
5545 
5546 		nrssi = bwi_nrssi_11g(mac);
5547 		if (nrssi == -32) {
5548 			for (i = 0; i < 4; ++i) {
5549 				RF_WRITE(mac, 0x7b, i);
5550 				DELAY(20);
5551 				nrssi = bwi_nrssi_11g(mac);
5552 				if (nrssi > -31 && rf7b == 0xffff)
5553 					rf7b = i;
5554 			}
5555 			if (rf7b == 0xffff)
5556 				rf7b = 3;
5557 		} else {
5558 			rf7b = 0;
5559 		}
5560 	}
5561 	RF_WRITE(mac, 0x7b, rf7b);
5562 
5563 	/*
5564 	 * Restore saved RF/PHY registers
5565 	 */
5566 	if (phy->phy_rev >= 6) {
5567 		for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) {
5568 			PHY_WRITE(mac, save_phy6_regs[phy6_idx],
5569 			    save_phy6[phy6_idx]);
5570 		}
5571 	}
5572 
5573 	/* Saved PHY registers 0, 1, 2 are handled later */
5574 	for (i = 3; i < SAVE_PHY_COMM_MAX; ++i)
5575 		PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
5576 
5577 	for (i = SAVE_RF_MAX - 1; i >= 0; --i)
5578 		RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
5579 
5580 	PHY_SETBITS(mac, 0x802, 0x3);
5581 	PHY_SETBITS(mac, 0x429, 0x8000);
5582 
5583 	bwi_set_gains(mac, NULL);
5584 
5585 	if (phy->phy_rev >= 6) {
5586 		for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) {
5587 			PHY_WRITE(mac, save_phy6_regs[phy6_idx],
5588 			    save_phy6[phy6_idx]);
5589 		}
5590 	}
5591 
5592 	PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0]);
5593 	PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2]);
5594 	PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1]);
5595 
5596 #undef SAVE_RF_MAX
5597 #undef SAVE_PHY_COMM_MAX
5598 #undef SAVE_PHY6_MAX
5599 }
5600 
5601 static void
5602 bwi_rf_calc_nrssi_slope_11g(struct bwi_mac *mac)
5603 {
5604 #define SAVE_RF_MAX		3
5605 #define SAVE_PHY_COMM_MAX	4
5606 #define SAVE_PHY3_MAX		8
5607 	static const uint16_t save_rf_regs[SAVE_RF_MAX] =
5608 	    { 0x7a, 0x52, 0x43 };
5609 	static const uint16_t save_phy_comm_regs[SAVE_PHY_COMM_MAX] =
5610 	    { 0x15, 0x5a, 0x59, 0x58 };
5611 	static const uint16_t save_phy3_regs[SAVE_PHY3_MAX] = {
5612 		0x002e, 0x002f, 0x080f, 0x0810,
5613 		0x0801, 0x0060, 0x0014, 0x0478
5614 	};
5615 
5616 	struct bwi_softc *sc = mac->mac_sc;
5617 	struct bwi_phy *phy = &mac->mac_phy;
5618 	struct bwi_rf *rf = &mac->mac_rf;
5619 	uint16_t save_rf[SAVE_RF_MAX];
5620 	uint16_t save_phy_comm[SAVE_PHY_COMM_MAX];
5621 	uint16_t save_phy3[SAVE_PHY3_MAX];
5622 	uint16_t ant_div, bbp_atten, chan_ex;
5623 	struct bwi_gains gains;
5624 	int16_t nrssi[2];
5625 	int i, phy3_idx = 0;
5626 
5627 	if (rf->rf_rev >= 9)
5628 		return;
5629 	else if (rf->rf_rev == 8)
5630 		bwi_rf_set_nrssi_ofs_11g(mac);
5631 
5632 	PHY_CLRBITS(mac, 0x429, 0x8000);
5633 	PHY_CLRBITS(mac, 0x802, 0x3);
5634 
5635 	/*
5636 	 * Save RF/PHY registers for later restoration
5637 	 */
5638 	ant_div = CSR_READ_2(sc, BWI_RF_ANTDIV);
5639 	CSR_SETBITS_2(sc, BWI_RF_ANTDIV, 0x8000);
5640 
5641 	for (i = 0; i < SAVE_RF_MAX; ++i)
5642 		save_rf[i] = RF_READ(mac, save_rf_regs[i]);
5643 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
5644 		save_phy_comm[i] = PHY_READ(mac, save_phy_comm_regs[i]);
5645 
5646 	bbp_atten = CSR_READ_2(sc, BWI_BBP_ATTEN);
5647 	chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX);
5648 
5649 	if (phy->phy_rev >= 3) {
5650 		for (i = 0; i < SAVE_PHY3_MAX; ++i)
5651 			save_phy3[i] = PHY_READ(mac, save_phy3_regs[i]);
5652 
5653 		PHY_WRITE(mac, 0x2e, 0);
5654 		PHY_WRITE(mac, 0x810, 0);
5655 
5656 		if (phy->phy_rev == 4 || phy->phy_rev == 6 ||
5657 		    phy->phy_rev == 7) {
5658 			PHY_SETBITS(mac, 0x478, 0x100);
5659 			PHY_SETBITS(mac, 0x810, 0x40);
5660 		} else if (phy->phy_rev == 3 || phy->phy_rev == 5)
5661 			PHY_CLRBITS(mac, 0x810, 0x40);
5662 
5663 		PHY_SETBITS(mac, 0x60, 0x40);
5664 		PHY_SETBITS(mac, 0x14, 0x200);
5665 	}
5666 
5667 	/*
5668 	 * Calculate nrssi0
5669 	 */
5670 	RF_SETBITS(mac, 0x7a, 0x70);
5671 
5672 	memset(&gains, 0, sizeof(gains));
5673 	gains.tbl_gain1 = 0;
5674 	gains.tbl_gain2 = 8;
5675 	gains.phy_gain = 0;
5676 	bwi_set_gains(mac, &gains);
5677 
5678 	RF_CLRBITS(mac, 0x7a, 0xff08);
5679 	if (phy->phy_rev >= 2) {
5680 		PHY_FILT_SETBITS(mac, 0x811, 0xffcf, 0x30);
5681 		PHY_FILT_SETBITS(mac, 0x812, 0xffcf, 0x10);
5682 	}
5683 
5684 	RF_SETBITS(mac, 0x7a, 0x80);
5685 	DELAY(20);
5686 	nrssi[0] = bwi_nrssi_11g(mac);
5687 
5688 	/*
5689 	 * Calculate nrssi1
5690 	 */
5691 	RF_CLRBITS(mac, 0x7a, 0xff80);
5692 	if (phy->phy_version >= 2)
5693 		PHY_FILT_SETBITS(mac, 0x3, 0xff9f, 0x40);
5694 	CSR_SETBITS_2(sc, BWI_RF_CHAN_EX, 0x2000);
5695 
5696 	RF_SETBITS(mac, 0x7a, 0xf);
5697 	PHY_WRITE(mac, 0x15, 0xf330);
5698 	if (phy->phy_rev >= 2) {
5699 		PHY_FILT_SETBITS(mac, 0x812, 0xffcf, 0x20);
5700 		PHY_FILT_SETBITS(mac, 0x811, 0xffcf, 0x20);
5701 	}
5702 
5703 	memset(&gains, 0, sizeof(gains));
5704 	gains.tbl_gain1 = 3;
5705 	gains.tbl_gain2 = 0;
5706 	gains.phy_gain = 1;
5707 	bwi_set_gains(mac, &gains);
5708 
5709 	if (rf->rf_rev == 8) {
5710 		RF_WRITE(mac, 0x43, 0x1f);
5711 	} else {
5712 		RF_FILT_SETBITS(mac, 0x52, 0xff0f, 0x60);
5713 		RF_FILT_SETBITS(mac, 0x43, 0xfff0, 0x9);
5714 	}
5715 	PHY_WRITE(mac, 0x5a, 0x480);
5716 	PHY_WRITE(mac, 0x59, 0x810);
5717 	PHY_WRITE(mac, 0x58, 0xd);
5718 	DELAY(20);
5719 
5720 	nrssi[1] = bwi_nrssi_11g(mac);
5721 
5722 	/*
5723 	 * Install calculated narrow RSSI values
5724 	 */
5725 	if (nrssi[1] == nrssi[0])
5726 		rf->rf_nrssi_slope = 0x10000;
5727 	else
5728 		rf->rf_nrssi_slope = 0x400000 / (nrssi[0] - nrssi[1]);
5729 	if (nrssi[0] >= -4) {
5730 		rf->rf_nrssi[0] = nrssi[1];
5731 		rf->rf_nrssi[1] = nrssi[0];
5732 	}
5733 
5734 	/*
5735 	 * Restore saved RF/PHY registers
5736 	 */
5737 	if (phy->phy_rev >= 3) {
5738 		for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) {
5739 			PHY_WRITE(mac, save_phy3_regs[phy3_idx],
5740 				  save_phy3[phy3_idx]);
5741 		}
5742 	}
5743 	if (phy->phy_rev >= 2) {
5744 		PHY_CLRBITS(mac, 0x812, 0x30);
5745 		PHY_CLRBITS(mac, 0x811, 0x30);
5746 	}
5747 
5748 	for (i = 0; i < SAVE_RF_MAX; ++i)
5749 		RF_WRITE(mac, save_rf_regs[i], save_rf[i]);
5750 
5751 	CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div);
5752 	CSR_WRITE_2(sc, BWI_BBP_ATTEN, bbp_atten);
5753 	CSR_WRITE_2(sc, BWI_RF_CHAN_EX, chan_ex);
5754 
5755 	for (i = 0; i < SAVE_PHY_COMM_MAX; ++i)
5756 		PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i]);
5757 
5758 	bwi_rf_workaround(mac, rf->rf_curchan);
5759 	PHY_SETBITS(mac, 0x802, 0x3);
5760 	bwi_set_gains(mac, NULL);
5761 	PHY_SETBITS(mac, 0x429, 0x8000);
5762 
5763 	if (phy->phy_rev >= 3) {
5764 		for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) {
5765 			PHY_WRITE(mac, save_phy3_regs[phy3_idx],
5766 			    save_phy3[phy3_idx]);
5767 		}
5768 	}
5769 
5770 	bwi_rf_init_sw_nrssi_table(mac);
5771 	bwi_rf_set_nrssi_thr_11g(mac);
5772 
5773 #undef SAVE_RF_MAX
5774 #undef SAVE_PHY_COMM_MAX
5775 #undef SAVE_PHY3_MAX
5776 }
5777 
5778 static void
5779 bwi_rf_init_sw_nrssi_table(struct bwi_mac *mac)
5780 {
5781 	struct bwi_rf *rf = &mac->mac_rf;
5782 	int d, i;
5783 
5784 	d = 0x1f - rf->rf_nrssi[0];
5785 	for (i = 0; i < BWI_NRSSI_TBLSZ; ++i) {
5786 		int val;
5787 
5788 		val = (((i - d) * rf->rf_nrssi_slope) / 0x10000) + 0x3a;
5789 		if (val < 0)
5790 			val = 0;
5791 		else if (val > 0x3f)
5792 			val = 0x3f;
5793 
5794 		rf->rf_nrssi_table[i] = val;
5795 	}
5796 }
5797 
5798 static void
5799 bwi_rf_init_hw_nrssi_table(struct bwi_mac *mac, uint16_t adjust)
5800 {
5801 	int i;
5802 
5803 	for (i = 0; i < BWI_NRSSI_TBLSZ; ++i) {
5804 		int16_t val;
5805 
5806 		val = bwi_nrssi_read(mac, i);
5807 
5808 		val -= adjust;
5809 		if (val < -32)
5810 			val = -32;
5811 		else if (val > 31)
5812 			val = 31;
5813 
5814 		bwi_nrssi_write(mac, i, val);
5815 	}
5816 }
5817 
5818 static void
5819 bwi_rf_set_nrssi_thr_11b(struct bwi_mac *mac)
5820 {
5821 	struct bwi_rf *rf = &mac->mac_rf;
5822 	int32_t thr;
5823 
5824 	if (rf->rf_type != BWI_RF_T_BCM2050 ||
5825 	    (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) == 0)
5826 		return;
5827 
5828 	/*
5829 	 * Calculate nrssi threshold
5830 	 */
5831 	if (rf->rf_rev >= 6) {
5832 		thr = (rf->rf_nrssi[1] - rf->rf_nrssi[0]) * 32;
5833 		thr += 20 * (rf->rf_nrssi[0] + 1);
5834 		thr /= 40;
5835 	} else {
5836 		thr = rf->rf_nrssi[1] - 5;
5837 	}
5838 	if (thr < 0)
5839 		thr = 0;
5840 	else if (thr > 0x3e)
5841 		thr = 0x3e;
5842 
5843 	PHY_READ(mac, BWI_PHYR_NRSSI_THR_11B);	/* dummy read */
5844 	PHY_WRITE(mac, BWI_PHYR_NRSSI_THR_11B, (((uint16_t)thr) << 8) | 0x1c);
5845 
5846 	if (rf->rf_rev >= 6) {
5847 		PHY_WRITE(mac, 0x87, 0xe0d);
5848 		PHY_WRITE(mac, 0x86, 0xc0b);
5849 		PHY_WRITE(mac, 0x85, 0xa09);
5850 		PHY_WRITE(mac, 0x84, 0x808);
5851 		PHY_WRITE(mac, 0x83, 0x808);
5852 		PHY_WRITE(mac, 0x82, 0x604);
5853 		PHY_WRITE(mac, 0x81, 0x302);
5854 		PHY_WRITE(mac, 0x80, 0x100);
5855 	}
5856 }
5857 
5858 static int32_t
5859 _nrssi_threshold(const struct bwi_rf *rf, int32_t val)
5860 {
5861 	val *= (rf->rf_nrssi[1] - rf->rf_nrssi[0]);
5862 	val += (rf->rf_nrssi[0] << 6);
5863 	if (val < 32)
5864 		val += 31;
5865 	else
5866 		val += 32;
5867 	val >>= 6;
5868 	if (val < -31)
5869 		val = -31;
5870 	else if (val > 31)
5871 		val = 31;
5872 
5873 	return (val);
5874 }
5875 
5876 static void
5877 bwi_rf_set_nrssi_thr_11g(struct bwi_mac *mac)
5878 {
5879 	int32_t thr1, thr2;
5880 	uint16_t thr;
5881 
5882 	/*
5883 	 * Find the two nrssi thresholds
5884 	 */
5885 	if ((mac->mac_phy.phy_flags & BWI_PHY_F_LINKED) == 0 ||
5886 	    (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) == 0) {
5887 	    	int16_t nrssi;
5888 
5889 		nrssi = bwi_nrssi_read(mac, 0x20);
5890 		if (nrssi >= 32)
5891 			nrssi -= 64;
5892 
5893 		if (nrssi < 3) {
5894 			thr1 = 0x2b;
5895 			thr2 = 0x27;
5896 		} else {
5897 			thr1 = 0x2d;
5898 			thr2 = 0x2b;
5899 		}
5900 	} else {
5901 		/* TODO Interfere mode */
5902 		thr1 = _nrssi_threshold(&mac->mac_rf, 0x11);
5903 		thr2 = _nrssi_threshold(&mac->mac_rf, 0xe);
5904 	}
5905 
5906 #define NRSSI_THR1_MASK		0x003f
5907 #define NRSSI_THR2_MASK		0x0fc0
5908 	thr = __SHIFTIN((uint32_t)thr1, NRSSI_THR1_MASK) |
5909 	    __SHIFTIN((uint32_t)thr2, NRSSI_THR2_MASK);
5910 	PHY_FILT_SETBITS(mac, BWI_PHYR_NRSSI_THR_11G, 0xf000, thr);
5911 #undef NRSSI_THR1_MASK
5912 #undef NRSSI_THR2_MASK
5913 }
5914 
5915 static void
5916 bwi_rf_clear_tssi(struct bwi_mac *mac)
5917 {
5918 	/* XXX use function pointer */
5919 	if (mac->mac_phy.phy_mode == IEEE80211_MODE_11A) {
5920 		/* TODO: 11A */
5921 	} else {
5922 		uint16_t val;
5923 		int i;
5924 
5925 		val = __SHIFTIN(BWI_INVALID_TSSI, BWI_LO_TSSI_MASK) |
5926 		    __SHIFTIN(BWI_INVALID_TSSI, BWI_HI_TSSI_MASK);
5927 
5928 		for (i = 0; i < 2; ++i) {
5929 			MOBJ_WRITE_2(mac, BWI_COMM_MOBJ,
5930 			    BWI_COMM_MOBJ_TSSI_DS + (i * 2), val);
5931 		}
5932 
5933 		for (i = 0; i < 2; ++i) {
5934 			MOBJ_WRITE_2(mac, BWI_COMM_MOBJ,
5935 			    BWI_COMM_MOBJ_TSSI_OFDM + (i * 2), val);
5936 		}
5937 	}
5938 }
5939 
5940 static void
5941 bwi_rf_clear_state(struct bwi_rf *rf)
5942 {
5943 	int i;
5944 
5945 	rf->rf_flags &= ~BWI_RF_CLEAR_FLAGS;
5946 	memset(rf->rf_lo, 0, sizeof(rf->rf_lo));
5947 	memset(rf->rf_lo_used, 0, sizeof(rf->rf_lo_used));
5948 
5949 	rf->rf_nrssi_slope = 0;
5950 	rf->rf_nrssi[0] = BWI_INVALID_NRSSI;
5951 	rf->rf_nrssi[1] = BWI_INVALID_NRSSI;
5952 
5953 	for (i = 0; i < BWI_NRSSI_TBLSZ; ++i)
5954 		rf->rf_nrssi_table[i] = i;
5955 
5956 	rf->rf_lo_gain = 0;
5957 	rf->rf_rx_gain = 0;
5958 
5959 	memcpy(rf->rf_txpower_map, rf->rf_txpower_map0,
5960 	      sizeof(rf->rf_txpower_map));
5961 	rf->rf_idle_tssi = rf->rf_idle_tssi0;
5962 }
5963 
5964 static void
5965 bwi_rf_on_11a(struct bwi_mac *mac)
5966 {
5967 	/* TODO: 11A */
5968 }
5969 
5970 static void
5971 bwi_rf_on_11bg(struct bwi_mac *mac)
5972 {
5973 	struct bwi_phy *phy = &mac->mac_phy;
5974 
5975 	PHY_WRITE(mac, 0x15, 0x8000);
5976 	PHY_WRITE(mac, 0x15, 0xcc00);
5977 	if (phy->phy_flags & BWI_PHY_F_LINKED)
5978 		PHY_WRITE(mac, 0x15, 0xc0);
5979 	else
5980 		PHY_WRITE(mac, 0x15, 0);
5981 
5982 	bwi_rf_set_chan(mac, 6 /* XXX */, 1);
5983 }
5984 
5985 static void
5986 bwi_rf_set_ant_mode(struct bwi_mac *mac, int ant_mode)
5987 {
5988 	struct bwi_softc *sc = mac->mac_sc;
5989 	struct bwi_phy *phy = &mac->mac_phy;
5990 	uint16_t val;
5991 
5992 	KASSERT(ant_mode == BWI_ANT_MODE_0 ||
5993 	    ant_mode == BWI_ANT_MODE_1 ||
5994 	    ant_mode == BWI_ANT_MODE_AUTO);
5995 
5996 	HFLAGS_CLRBITS(mac, BWI_HFLAG_AUTO_ANTDIV);
5997 
5998 	if (phy->phy_mode == IEEE80211_MODE_11B) {
5999 		/* NOTE: v4/v3 conflicts, take v3 */
6000 		if (mac->mac_rev == 2)
6001 			val = BWI_ANT_MODE_AUTO;
6002 		else
6003 			val = ant_mode;
6004 		val <<= 7;
6005 		PHY_FILT_SETBITS(mac, 0x3e2, 0xfe7f, val);
6006 	} else {	/* 11a/g */
6007 		/* XXX reg/value naming */
6008 		val = ant_mode << 7;
6009 		PHY_FILT_SETBITS(mac, 0x401, 0x7e7f, val);
6010 
6011 		if (ant_mode == BWI_ANT_MODE_AUTO)
6012 			PHY_CLRBITS(mac, 0x42b, 0x100);
6013 
6014 		if (phy->phy_mode == IEEE80211_MODE_11A) {
6015 			/* TODO: 11A */
6016 		} else {	/* 11g */
6017 			if (ant_mode == BWI_ANT_MODE_AUTO)
6018 				PHY_SETBITS(mac, 0x48c, 0x2000);
6019 			else
6020 				PHY_CLRBITS(mac, 0x48c, 0x2000);
6021 
6022 			if (phy->phy_rev >= 2) {
6023 				PHY_SETBITS(mac, 0x461, 0x10);
6024 				PHY_FILT_SETBITS(mac, 0x4ad, 0xff00, 0x15);
6025 				if (phy->phy_rev == 2) {
6026 					PHY_WRITE(mac, 0x427, 0x8);
6027 				} else {
6028 					PHY_FILT_SETBITS(mac, 0x427,
6029 							 0xff00, 0x8);
6030 				}
6031 
6032 				if (phy->phy_rev >= 6)
6033 					PHY_WRITE(mac, 0x49b, 0xdc);
6034 			}
6035 		}
6036 	}
6037 
6038 	/* XXX v4 set AUTO_ANTDIV unconditionally */
6039 	if (ant_mode == BWI_ANT_MODE_AUTO)
6040 		HFLAGS_SETBITS(mac, BWI_HFLAG_AUTO_ANTDIV);
6041 
6042 	val = ant_mode << 8;
6043 	MOBJ_FILT_SETBITS_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_TX_BEACON,
6044 	    0xfc3f, val);
6045 	MOBJ_FILT_SETBITS_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_TX_ACK,
6046 	    0xfc3f, val);
6047 	MOBJ_FILT_SETBITS_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_TX_PROBE_RESP,
6048 	    0xfc3f, val);
6049 
6050 	/* XXX what's these */
6051 	if (phy->phy_mode == IEEE80211_MODE_11B)
6052 		CSR_SETBITS_2(sc, 0x5e, 0x4);
6053 
6054 	CSR_WRITE_4(sc, 0x100, 0x1000000);
6055 	if (mac->mac_rev < 5)
6056 		CSR_WRITE_4(sc, 0x10c, 0x1000000);
6057 
6058 	mac->mac_rf.rf_ant_mode = ant_mode;
6059 }
6060 
6061 static int
6062 bwi_rf_get_latest_tssi(struct bwi_mac *mac, int8_t tssi[], uint16_t ofs)
6063 {
6064 	int i;
6065 
6066 	for (i = 0; i < 4; ) {
6067 		uint16_t val;
6068 
6069 		val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, ofs + i);
6070 		tssi[i++] = (int8_t)__SHIFTOUT(val, BWI_LO_TSSI_MASK);
6071 		tssi[i++] = (int8_t)__SHIFTOUT(val, BWI_HI_TSSI_MASK);
6072 	}
6073 
6074 	for (i = 0; i < 4; ++i) {
6075 		if (tssi[i] == BWI_INVALID_TSSI)
6076 			return (EINVAL);
6077 	}
6078 
6079 	return (0);
6080 }
6081 
6082 static int
6083 bwi_rf_tssi2dbm(struct bwi_mac *mac, int8_t tssi, int8_t *txpwr)
6084 {
6085 	struct bwi_rf *rf = &mac->mac_rf;
6086 	int pwr_idx;
6087 
6088 	pwr_idx = rf->rf_idle_tssi + (int)tssi - rf->rf_base_tssi;
6089 #if 0
6090 	if (pwr_idx < 0 || pwr_idx >= BWI_TSSI_MAX)
6091 		return (EINVAL);
6092 #else
6093 	if (pwr_idx < 0)
6094 		pwr_idx = 0;
6095 	else if (pwr_idx >= BWI_TSSI_MAX)
6096 		pwr_idx = BWI_TSSI_MAX - 1;
6097 #endif
6098 	*txpwr = rf->rf_txpower_map[pwr_idx];
6099 
6100 	return (0);
6101 }
6102 
6103 static int
6104 bwi_rf_calc_rssi_bcm2050(struct bwi_mac *mac, const struct bwi_rxbuf_hdr *hdr)
6105 {
6106 	uint16_t flags1, flags3;
6107 	int rssi, lna_gain;
6108 
6109 	rssi = hdr->rxh_rssi;
6110 	flags1 = le16toh(hdr->rxh_flags1);
6111 	flags3 = le16toh(hdr->rxh_flags3);
6112 
6113 #define NEW_BCM2050_RSSI
6114 #ifdef NEW_BCM2050_RSSI
6115 	if (flags1 & BWI_RXH_F1_OFDM) {
6116 		if (rssi > 127)
6117 			rssi -= 256;
6118 		if (flags3 & BWI_RXH_F3_BCM2050_RSSI)
6119 			rssi += 17;
6120 		else
6121 			rssi -= 4;
6122 		return (rssi);
6123 	}
6124 
6125 	if (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) {
6126 		struct bwi_rf *rf = &mac->mac_rf;
6127 
6128 		if (rssi >= BWI_NRSSI_TBLSZ)
6129 			rssi = BWI_NRSSI_TBLSZ - 1;
6130 
6131 		rssi = ((31 - (int)rf->rf_nrssi_table[rssi]) * -131) / 128;
6132 		rssi -= 67;
6133 	} else {
6134 		rssi = ((31 - rssi) * -149) / 128;
6135 		rssi -= 68;
6136 	}
6137 
6138 	if (mac->mac_phy.phy_mode != IEEE80211_MODE_11G)
6139 		return (rssi);
6140 
6141 	if (flags3 & BWI_RXH_F3_BCM2050_RSSI)
6142 		rssi += 20;
6143 
6144 	lna_gain = __SHIFTOUT(le16toh(hdr->rxh_phyinfo),
6145 	    BWI_RXH_PHYINFO_LNAGAIN);
6146 /*	[TRC: XXX This causes some seriously verbose output.  I hope it
6147 	just verbose and not actually a symptom of a problem.]
6148 
6149 	DPRINTF(mac->mac_sc, BWI_DBG_RF | BWI_DBG_RX,
6150 	    "lna_gain %d, phyinfo 0x%04x\n",
6151 	    lna_gain, le16toh(hdr->rxh_phyinfo));
6152 */
6153 	switch (lna_gain) {
6154 	case 0:
6155 		rssi += 27;
6156 		break;
6157 	case 1:
6158 		rssi += 6;
6159 		break;
6160 	case 2:
6161 		rssi += 12;
6162 		break;
6163 	case 3:
6164 		/*
6165 		 * XXX
6166 		 * According to v3 spec, we should do _nothing_ here,
6167 		 * but it seems that the result RSSI will be too low
6168 		 * (relative to what ath(4) says).  Raise it a little
6169 		 * bit.
6170 		 */
6171 		rssi += 5;
6172 		break;
6173 	default:
6174 		panic("impossible lna gain %d", lna_gain);
6175 	}
6176 #else	/* !NEW_BCM2050_RSSI */
6177 	lna_gain = 0; /* shut up gcc warning */
6178 
6179 	if (flags1 & BWI_RXH_F1_OFDM) {
6180 		if (rssi > 127)
6181 			rssi -= 256;
6182 		rssi = (rssi * 73) / 64;
6183 
6184 		if (flags3 & BWI_RXH_F3_BCM2050_RSSI)
6185 			rssi += 25;
6186 		else
6187 			rssi -= 3;
6188 		return (rssi);
6189 	}
6190 
6191 	if (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI) {
6192 		struct bwi_rf *rf = &mac->mac_rf;
6193 
6194 		if (rssi >= BWI_NRSSI_TBLSZ)
6195 			rssi = BWI_NRSSI_TBLSZ - 1;
6196 
6197 		rssi = ((31 - (int)rf->rf_nrssi_table[rssi]) * -131) / 128;
6198 		rssi -= 57;
6199 	} else {
6200 		rssi = ((31 - rssi) * -149) / 128;
6201 		rssi -= 68;
6202 	}
6203 
6204 	if (mac->mac_phy.phy_mode != IEEE80211_MODE_11G)
6205 		return (rssi);
6206 
6207 	if (flags3 & BWI_RXH_F3_BCM2050_RSSI)
6208 		rssi += 25;
6209 #endif	/* NEW_BCM2050_RSSI */
6210 	return (rssi);
6211 }
6212 
6213 static int
6214 bwi_rf_calc_rssi_bcm2053(struct bwi_mac *mac, const struct bwi_rxbuf_hdr *hdr)
6215 {
6216 	uint16_t flags1;
6217 	int rssi;
6218 
6219 	rssi = (((int)hdr->rxh_rssi - 11) * 103) / 64;
6220 
6221 	flags1 = le16toh(hdr->rxh_flags1);
6222 	if (flags1 & BWI_RXH_F1_BCM2053_RSSI)
6223 		rssi -= 109;
6224 	else
6225 		rssi -= 83;
6226 
6227 	return (rssi);
6228 }
6229 
6230 static int
6231 bwi_rf_calc_rssi_bcm2060(struct bwi_mac *mac, const struct bwi_rxbuf_hdr *hdr)
6232 {
6233 	int rssi;
6234 
6235 	rssi = hdr->rxh_rssi;
6236 	if (rssi > 127)
6237 		rssi -= 256;
6238 
6239 	return (rssi);
6240 }
6241 
6242 static uint16_t
6243 bwi_rf_lo_measure_11b(struct bwi_mac *mac)
6244 {
6245 	uint16_t val;
6246 	int i;
6247 
6248 	val = 0;
6249 	for (i = 0; i < 10; ++i) {
6250 		PHY_WRITE(mac, 0x15, 0xafa0);
6251 		DELAY(1);
6252 		PHY_WRITE(mac, 0x15, 0xefa0);
6253 		DELAY(10);
6254 		PHY_WRITE(mac, 0x15, 0xffa0);
6255 		DELAY(40);
6256 
6257 		val += PHY_READ(mac, 0x2c);
6258 	}
6259 
6260 	return (val);
6261 }
6262 
6263 static void
6264 bwi_rf_lo_update_11b(struct bwi_mac *mac)
6265 {
6266 	struct bwi_softc *sc = mac->mac_sc;
6267 	struct bwi_rf *rf = &mac->mac_rf;
6268 	struct rf_saveregs regs;
6269 	uint16_t rf_val, phy_val, min_val, val;
6270 	uint16_t rf52, bphy_ctrl;
6271 	int i;
6272 
6273 	DPRINTF(sc, BWI_DBG_RF | BWI_DBG_INIT, "%s enter\n", __func__);
6274 
6275 	memset(&regs, 0, sizeof(regs));
6276 	bphy_ctrl = 0;
6277 
6278 	/*
6279 	 * Save RF/PHY registers for later restoration
6280 	 */
6281 	SAVE_PHY_REG(mac, &regs, 15);
6282 	rf52 = RF_READ(mac, 0x52) & 0xfff0;
6283 	if (rf->rf_type == BWI_RF_T_BCM2050) {
6284 		SAVE_PHY_REG(mac, &regs, 0a);
6285 		SAVE_PHY_REG(mac, &regs, 2a);
6286 		SAVE_PHY_REG(mac, &regs, 35);
6287 		SAVE_PHY_REG(mac, &regs, 03);
6288 		SAVE_PHY_REG(mac, &regs, 01);
6289 		SAVE_PHY_REG(mac, &regs, 30);
6290 
6291 		SAVE_RF_REG(mac, &regs, 43);
6292 		SAVE_RF_REG(mac, &regs, 7a);
6293 
6294 		bphy_ctrl = CSR_READ_2(sc, BWI_BPHY_CTRL);
6295 
6296 		SAVE_RF_REG(mac, &regs, 52);
6297 		regs.rf_52 &= 0xf0;
6298 
6299 		PHY_WRITE(mac, 0x30, 0xff);
6300 		CSR_WRITE_2(sc, BWI_PHY_CTRL, 0x3f3f);
6301 		PHY_WRITE(mac, 0x35, regs.phy_35 & 0xff7f);
6302 		RF_WRITE(mac, 0x7a, regs.rf_7a & 0xfff0);
6303 	}
6304 
6305 	PHY_WRITE(mac, 0x15, 0xb000);
6306 
6307 	if (rf->rf_type == BWI_RF_T_BCM2050) {
6308 		PHY_WRITE(mac, 0x2b, 0x203);
6309 		PHY_WRITE(mac, 0x2a, 0x8a3);
6310 	} else {
6311 		PHY_WRITE(mac, 0x2b, 0x1402);
6312 	}
6313 
6314 	/*
6315 	 * Setup RF signal
6316 	 */
6317 	rf_val = 0;
6318 	min_val = UINT16_MAX;
6319 
6320 	for (i = 0; i < 4; ++i) {
6321 		RF_WRITE(mac, 0x52, rf52 | i);
6322 		bwi_rf_lo_measure_11b(mac);	/* Ignore return value */
6323 	}
6324 	for (i = 0; i < 10; ++i) {
6325 		RF_WRITE(mac, 0x52, rf52 | i);
6326 
6327 		val = bwi_rf_lo_measure_11b(mac) / 10;
6328 		if (val < min_val) {
6329 			min_val = val;
6330 			rf_val = i;
6331 		}
6332 	}
6333 	RF_WRITE(mac, 0x52, rf52 | rf_val);
6334 
6335 	/*
6336 	 * Setup PHY signal
6337 	 */
6338 	phy_val = 0;
6339 	min_val = UINT16_MAX;
6340 
6341 	for (i = -4; i < 5; i += 2) {
6342 		int j;
6343 
6344 		for (j = -4; j < 5; j += 2) {
6345 			uint16_t phy2f;
6346 
6347 			phy2f = (0x100 * i) + j;
6348 			if (j < 0)
6349 				phy2f += 0x100;
6350 			PHY_WRITE(mac, 0x2f, phy2f);
6351 
6352 			val = bwi_rf_lo_measure_11b(mac) / 10;
6353 			if (val < min_val) {
6354 				min_val = val;
6355 				phy_val = phy2f;
6356 			}
6357 		}
6358 	}
6359 	PHY_WRITE(mac, 0x2f, phy_val + 0x101);
6360 
6361 	/*
6362 	 * Restore saved RF/PHY registers
6363 	 */
6364 	if (rf->rf_type == BWI_RF_T_BCM2050) {
6365 		RESTORE_PHY_REG(mac, &regs, 0a);
6366 		RESTORE_PHY_REG(mac, &regs, 2a);
6367 		RESTORE_PHY_REG(mac, &regs, 35);
6368 		RESTORE_PHY_REG(mac, &regs, 03);
6369 		RESTORE_PHY_REG(mac, &regs, 01);
6370 		RESTORE_PHY_REG(mac, &regs, 30);
6371 
6372 		RESTORE_RF_REG(mac, &regs, 43);
6373 		RESTORE_RF_REG(mac, &regs, 7a);
6374 
6375 		RF_FILT_SETBITS(mac, 0x52, 0xf, regs.rf_52);
6376 
6377 		CSR_WRITE_2(sc, BWI_BPHY_CTRL, bphy_ctrl);
6378 	}
6379 	RESTORE_PHY_REG(mac, &regs, 15);
6380 
6381 	bwi_rf_workaround(mac, rf->rf_curchan);
6382 }
6383 
6384 /* INTERFACE */
6385 
6386 static uint16_t
6387 bwi_read_sprom(struct bwi_softc *sc, uint16_t ofs)
6388 {
6389 	return (CSR_READ_2(sc, ofs + BWI_SPROM_START));
6390 }
6391 
6392 static void
6393 bwi_setup_desc32(struct bwi_softc *sc, struct bwi_desc32 *desc_array,
6394     int ndesc, int desc_idx, bus_addr_t paddr, int buf_len, int tx)
6395 {
6396 	struct bwi_desc32 *desc = &desc_array[desc_idx];
6397 	uint32_t ctrl, addr, addr_hi, addr_lo;
6398 
6399 	addr_lo = __SHIFTOUT(paddr, BWI_DESC32_A_ADDR_MASK);
6400 	addr_hi = __SHIFTOUT(paddr, BWI_DESC32_A_FUNC_MASK);
6401 
6402 	addr = __SHIFTIN(addr_lo, BWI_DESC32_A_ADDR_MASK) |
6403 	    __SHIFTIN(BWI_DESC32_A_FUNC_TXRX, BWI_DESC32_A_FUNC_MASK);
6404 
6405 	ctrl = __SHIFTIN(buf_len, BWI_DESC32_C_BUFLEN_MASK) |
6406 	     __SHIFTIN(addr_hi, BWI_DESC32_C_ADDRHI_MASK);
6407 	if (desc_idx == ndesc - 1)
6408 		ctrl |= BWI_DESC32_C_EOR;
6409 	if (tx) {
6410 		/* XXX */
6411 		ctrl |= BWI_DESC32_C_FRAME_START |
6412 		    BWI_DESC32_C_FRAME_END |
6413 		    BWI_DESC32_C_INTR;
6414 	}
6415 
6416 	desc->addr = htole32(addr);
6417 	desc->ctrl = htole32(ctrl);
6418 }
6419 
6420 static void
6421 bwi_power_on(struct bwi_softc *sc, int with_pll)
6422 {
6423 	uint32_t gpio_in, gpio_out, gpio_en, status;
6424 
6425 	DPRINTF(sc, BWI_DBG_MISC, "%s\n", __func__);
6426 
6427 	gpio_in = (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_IN);
6428 	if (gpio_in & BWI_PCIM_GPIO_PWR_ON)
6429 		goto back;
6430 
6431 	gpio_out = (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_OUT);
6432 	gpio_en = (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_ENABLE);
6433 
6434 	gpio_out |= BWI_PCIM_GPIO_PWR_ON;
6435 	gpio_en |= BWI_PCIM_GPIO_PWR_ON;
6436 	if (with_pll) {
6437 		/* Turn off PLL first */
6438 		gpio_out |= BWI_PCIM_GPIO_PLL_PWR_OFF;
6439 		gpio_en |= BWI_PCIM_GPIO_PLL_PWR_OFF;
6440 	}
6441 
6442 	(sc->sc_conf_write)(sc, BWI_PCIR_GPIO_OUT, gpio_out);
6443 	(sc->sc_conf_write)(sc, BWI_PCIR_GPIO_ENABLE, gpio_en);
6444 	DELAY(1000);
6445 
6446 	if (with_pll) {
6447 		/* Turn on PLL */
6448 		gpio_out &= ~BWI_PCIM_GPIO_PLL_PWR_OFF;
6449 		(sc->sc_conf_write)(sc, BWI_PCIR_GPIO_OUT, gpio_out);
6450 		DELAY(5000);
6451 	}
6452 
6453 back:
6454 	/* [TRC: XXX This looks totally wrong -- what's PCI doing in here?] */
6455 	/* Clear "Signaled Target Abort" */
6456 	status = (sc->sc_conf_read)(sc, PCI_COMMAND_STATUS_REG);
6457 	status &= ~PCI_STATUS_TARGET_TARGET_ABORT;
6458 	(sc->sc_conf_write)(sc, PCI_COMMAND_STATUS_REG, status);
6459 }
6460 
6461 static int
6462 bwi_power_off(struct bwi_softc *sc, int with_pll)
6463 {
6464 	uint32_t gpio_out, gpio_en;
6465 
6466 	DPRINTF(sc, BWI_DBG_MISC, "%s\n", __func__);
6467 
6468 	(sc->sc_conf_read)(sc, BWI_PCIR_GPIO_IN); /* dummy read */
6469 	gpio_out = (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_OUT);
6470 	gpio_en = (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_ENABLE);
6471 
6472 	gpio_out &= ~BWI_PCIM_GPIO_PWR_ON;
6473 	gpio_en |= BWI_PCIM_GPIO_PWR_ON;
6474 	if (with_pll) {
6475 		gpio_out |= BWI_PCIM_GPIO_PLL_PWR_OFF;
6476 		gpio_en |= BWI_PCIM_GPIO_PLL_PWR_OFF;
6477 	}
6478 
6479 	(sc->sc_conf_write)(sc, BWI_PCIR_GPIO_OUT, gpio_out);
6480 	(sc->sc_conf_write)(sc, BWI_PCIR_GPIO_ENABLE, gpio_en);
6481 
6482 	return (0);
6483 }
6484 
6485 static int
6486 bwi_regwin_switch(struct bwi_softc *sc, struct bwi_regwin *rw,
6487     struct bwi_regwin **old_rw)
6488 {
6489 	int error;
6490 
6491 	if (old_rw != NULL)
6492 		*old_rw = NULL;
6493 
6494 	if (!BWI_REGWIN_EXIST(rw))
6495 		return (EINVAL);
6496 
6497 	if (sc->sc_cur_regwin != rw) {
6498 		error = bwi_regwin_select(sc, rw->rw_id);
6499 		if (error) {
6500 			aprint_error_dev(sc->sc_dev,
6501 			    "can't select regwin %d\n", rw->rw_id);
6502 			return (error);
6503 		}
6504 	}
6505 
6506 	if (old_rw != NULL)
6507 		*old_rw = sc->sc_cur_regwin;
6508 	sc->sc_cur_regwin = rw;
6509 
6510 	return (0);
6511 }
6512 
6513 static int
6514 bwi_regwin_select(struct bwi_softc *sc, int id)
6515 {
6516 	uint32_t win = BWI_PCIM_REGWIN(id);
6517 	int i;
6518 
6519 #define RETRY_MAX	50
6520 	for (i = 0; i < RETRY_MAX; ++i) {
6521 		(sc->sc_conf_write)(sc, BWI_PCIR_SEL_REGWIN, win);
6522 		if ((sc->sc_conf_read)(sc, BWI_PCIR_SEL_REGWIN) == win)
6523 			return (0);
6524 		DELAY(10);
6525 	}
6526 #undef RETRY_MAX
6527 
6528 	return (ENXIO);
6529 }
6530 
6531 static void
6532 bwi_regwin_info(struct bwi_softc *sc, uint16_t *type, uint8_t *rev)
6533 {
6534 	uint32_t val;
6535 
6536 	val = CSR_READ_4(sc, BWI_ID_HI);
6537 	*type = BWI_ID_HI_REGWIN_TYPE(val);
6538 	*rev = BWI_ID_HI_REGWIN_REV(val);
6539 
6540 	DPRINTF(sc, BWI_DBG_ATTACH, "regwin: type 0x%03x, rev %d,"
6541 	    " vendor 0x%04x\n", *type, *rev,
6542 	    __SHIFTOUT(val, BWI_ID_HI_REGWIN_VENDOR_MASK));
6543 }
6544 
6545 static void
6546 bwi_led_attach(struct bwi_softc *sc)
6547 {
6548 	const uint8_t *led_act = NULL;
6549 	uint16_t gpio, val[BWI_LED_MAX];
6550 	int i;
6551 
6552 	for (i = 0; i < __arraycount(bwi_vendor_led_act); ++i) {
6553 		if (sc->sc_pci_subvid == bwi_vendor_led_act[i].vid) {
6554 			led_act = bwi_vendor_led_act[i].led_act;
6555 			break;
6556 		}
6557 	}
6558 	if (led_act == NULL)
6559 		led_act = bwi_default_led_act;
6560 
6561 	gpio = bwi_read_sprom(sc, BWI_SPROM_GPIO01);
6562 	val[0] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_0);
6563 	val[1] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_1);
6564 
6565 	gpio = bwi_read_sprom(sc, BWI_SPROM_GPIO23);
6566 	val[2] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_2);
6567 	val[3] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_3);
6568 
6569 	for (i = 0; i < BWI_LED_MAX; ++i) {
6570 		struct bwi_led *led = &sc->sc_leds[i];
6571 
6572 		if (val[i] == 0xff) {
6573 			led->l_act = led_act[i];
6574 		} else {
6575 			if (val[i] & BWI_LED_ACT_LOW)
6576 				led->l_flags |= BWI_LED_F_ACTLOW;
6577 			led->l_act = __SHIFTOUT(val[i], BWI_LED_ACT_MASK);
6578 		}
6579 		led->l_mask = (1 << i);
6580 
6581 		if (led->l_act == BWI_LED_ACT_BLINK_SLOW ||
6582 		    led->l_act == BWI_LED_ACT_BLINK_POLL ||
6583 		    led->l_act == BWI_LED_ACT_BLINK) {
6584 			led->l_flags |= BWI_LED_F_BLINK;
6585 			if (led->l_act == BWI_LED_ACT_BLINK_POLL)
6586 				led->l_flags |= BWI_LED_F_POLLABLE;
6587 			else if (led->l_act == BWI_LED_ACT_BLINK_SLOW)
6588 				led->l_flags |= BWI_LED_F_SLOW;
6589 
6590 			if (sc->sc_blink_led == NULL) {
6591 				sc->sc_blink_led = led;
6592 				if (led->l_flags & BWI_LED_F_SLOW)
6593 					BWI_LED_SLOWDOWN(sc->sc_led_idle);
6594 			}
6595 		}
6596 
6597 		DPRINTF(sc, BWI_DBG_LED | BWI_DBG_ATTACH,
6598 		    "%dth led, act %d, lowact %d\n", i, led->l_act,
6599 		    led->l_flags & BWI_LED_F_ACTLOW);
6600 	}
6601 	callout_init(&sc->sc_led_blink_ch, 0);
6602 }
6603 
6604 static uint16_t
6605 bwi_led_onoff(const struct bwi_led *led, uint16_t val, int on)
6606 {
6607 	if (led->l_flags & BWI_LED_F_ACTLOW)
6608 		on = !on;
6609 	if (on)
6610 		val |= led->l_mask;
6611 	else
6612 		val &= ~led->l_mask;
6613 
6614 	return (val);
6615 }
6616 
6617 static void
6618 bwi_led_newstate(struct bwi_softc *sc, enum ieee80211_state nstate)
6619 {
6620 	struct ieee80211com *ic = &sc->sc_ic;
6621 	struct ifnet *ifp = &sc->sc_if;
6622 	uint16_t val;
6623 	int i;
6624 
6625 	if (nstate == IEEE80211_S_INIT) {
6626 		callout_stop(&sc->sc_led_blink_ch);
6627 		sc->sc_led_blinking = 0;
6628 	}
6629 
6630 	if ((ifp->if_flags & IFF_RUNNING) == 0)
6631 		return;
6632 
6633 	val = CSR_READ_2(sc, BWI_MAC_GPIO_CTRL);
6634 	for (i = 0; i < BWI_LED_MAX; ++i) {
6635 		struct bwi_led *led = &sc->sc_leds[i];
6636 		int on;
6637 
6638 		if (led->l_act == BWI_LED_ACT_UNKN ||
6639 		    led->l_act == BWI_LED_ACT_NULL)
6640 			continue;
6641 
6642 		if ((led->l_flags & BWI_LED_F_BLINK) &&
6643 		    nstate != IEEE80211_S_INIT)
6644 			continue;
6645 
6646 		switch (led->l_act) {
6647 		case BWI_LED_ACT_ON:	/* Always on */
6648 			on = 1;
6649 			break;
6650 		case BWI_LED_ACT_OFF:	/* Always off */
6651 		case BWI_LED_ACT_5GHZ:	/* TODO: 11A */
6652 			on = 0;
6653 			break;
6654 		default:
6655 			on = 1;
6656 			switch (nstate) {
6657 			case IEEE80211_S_INIT:
6658 				on = 0;
6659 				break;
6660 			case IEEE80211_S_RUN:
6661 				if (led->l_act == BWI_LED_ACT_11G &&
6662 				    ic->ic_curmode != IEEE80211_MODE_11G)
6663 					on = 0;
6664 				break;
6665 			default:
6666 				if (led->l_act == BWI_LED_ACT_ASSOC)
6667 					on = 0;
6668 				break;
6669 			}
6670 			break;
6671 		}
6672 
6673 		val = bwi_led_onoff(led, val, on);
6674 	}
6675 	CSR_WRITE_2(sc, BWI_MAC_GPIO_CTRL, val);
6676 }
6677 
6678 static void
6679 bwi_led_event(struct bwi_softc *sc, int event)
6680 {
6681 	struct bwi_led *led = sc->sc_blink_led;
6682 	int rate;
6683 
6684 	if (event == BWI_LED_EVENT_POLL) {
6685 		if ((led->l_flags & BWI_LED_F_POLLABLE) == 0)
6686 			return;
6687 		if (ticks - sc->sc_led_ticks < sc->sc_led_idle)
6688 			return;
6689 	}
6690 
6691 	sc->sc_led_ticks = ticks;
6692 	if (sc->sc_led_blinking)
6693 		return;
6694 
6695 	switch (event) {
6696 	case BWI_LED_EVENT_RX:
6697 		rate = sc->sc_rx_rate;
6698 		break;
6699 	case BWI_LED_EVENT_TX:
6700 		rate = sc->sc_tx_rate;
6701 		break;
6702 	case BWI_LED_EVENT_POLL:
6703 		rate = 0;
6704 		break;
6705 	default:
6706 		panic("unknown LED event %d\n", event);
6707 		break;
6708 	}
6709 	bwi_led_blink_start(sc, bwi_led_duration[rate].on_dur,
6710 	    bwi_led_duration[rate].off_dur);
6711 }
6712 
6713 static void
6714 bwi_led_blink_start(struct bwi_softc *sc, int on_dur, int off_dur)
6715 {
6716 	struct bwi_led *led = sc->sc_blink_led;
6717 	uint16_t val;
6718 
6719 	val = CSR_READ_2(sc, BWI_MAC_GPIO_CTRL);
6720 	val = bwi_led_onoff(led, val, 1);
6721 	CSR_WRITE_2(sc, BWI_MAC_GPIO_CTRL, val);
6722 
6723 	if (led->l_flags & BWI_LED_F_SLOW) {
6724 		BWI_LED_SLOWDOWN(on_dur);
6725 		BWI_LED_SLOWDOWN(off_dur);
6726 	}
6727 
6728 	sc->sc_led_blinking = 1;
6729 	sc->sc_led_blink_offdur = off_dur;
6730 
6731 	callout_reset(&sc->sc_led_blink_ch, on_dur, bwi_led_blink_next, sc);
6732 }
6733 
6734 static void
6735 bwi_led_blink_next(void *xsc)
6736 {
6737 	struct bwi_softc *sc = xsc;
6738 	uint16_t val;
6739 
6740 	val = CSR_READ_2(sc, BWI_MAC_GPIO_CTRL);
6741 	val = bwi_led_onoff(sc->sc_blink_led, val, 0);
6742 	CSR_WRITE_2(sc, BWI_MAC_GPIO_CTRL, val);
6743 
6744 	callout_reset(&sc->sc_led_blink_ch, sc->sc_led_blink_offdur,
6745 	    bwi_led_blink_end, sc);
6746 }
6747 
6748 static void
6749 bwi_led_blink_end(void *xsc)
6750 {
6751 	struct bwi_softc *sc = xsc;
6752 
6753 	sc->sc_led_blinking = 0;
6754 }
6755 
6756 static int
6757 bwi_bbp_attach(struct bwi_softc *sc)
6758 {
6759 	uint16_t bbp_id, rw_type;
6760 	uint8_t rw_rev;
6761 	uint32_t info;
6762 	int error, nregwin, i;
6763 
6764 	/*
6765 	 * Get 0th regwin information
6766 	 * NOTE: 0th regwin should exist
6767 	 */
6768 	error = bwi_regwin_select(sc, 0);
6769 	if (error) {
6770 		aprint_error_dev(sc->sc_dev, "can't select regwin 0\n");
6771 		return (error);
6772 	}
6773 	bwi_regwin_info(sc, &rw_type, &rw_rev);
6774 
6775 	/*
6776 	 * Find out BBP id
6777 	 */
6778 	bbp_id = 0;
6779 	info = 0;
6780 	if (rw_type == BWI_REGWIN_T_COM) {
6781 		info = CSR_READ_4(sc, BWI_INFO);
6782 		bbp_id = __SHIFTOUT(info, BWI_INFO_BBPID_MASK);
6783 
6784 		BWI_CREATE_REGWIN(&sc->sc_com_regwin, 0, rw_type, rw_rev);
6785 
6786 		sc->sc_cap = CSR_READ_4(sc, BWI_CAPABILITY);
6787 	} else {
6788 		uint16_t did = sc->sc_pci_did;
6789 		uint8_t revid = sc->sc_pci_revid;
6790 
6791 		for (i = 0; i < __arraycount(bwi_bbpid_map); ++i) {
6792 			if (did >= bwi_bbpid_map[i].did_min &&
6793 			    did <= bwi_bbpid_map[i].did_max) {
6794 				bbp_id = bwi_bbpid_map[i].bbp_id;
6795 				break;
6796 			}
6797 		}
6798 		if (bbp_id == 0) {
6799 			aprint_error_dev(sc->sc_dev, "no BBP id for device id"
6800 			    " 0x%04x\n", did);
6801 			return (ENXIO);
6802 		}
6803 
6804 		info = __SHIFTIN(revid, BWI_INFO_BBPREV_MASK) |
6805 		    __SHIFTIN(0, BWI_INFO_BBPPKG_MASK);
6806 	}
6807 
6808 	/*
6809 	 * Find out number of regwins
6810 	 */
6811 	nregwin = 0;
6812 	if (rw_type == BWI_REGWIN_T_COM && rw_rev >= 4) {
6813 		nregwin = __SHIFTOUT(info, BWI_INFO_NREGWIN_MASK);
6814 	} else {
6815 		for (i = 0; i < __arraycount(bwi_regwin_count); ++i) {
6816 			if (bwi_regwin_count[i].bbp_id == bbp_id) {
6817 				nregwin = bwi_regwin_count[i].nregwin;
6818 				break;
6819 			}
6820 		}
6821 		if (nregwin == 0) {
6822 			aprint_error_dev(sc->sc_dev, "no number of win for"
6823 			    " BBP id 0x%04x\n", bbp_id);
6824 			return (ENXIO);
6825 		}
6826 	}
6827 
6828 	/* Record BBP id/rev for later using */
6829 	sc->sc_bbp_id = bbp_id;
6830 	sc->sc_bbp_rev = __SHIFTOUT(info, BWI_INFO_BBPREV_MASK);
6831 	sc->sc_bbp_pkg = __SHIFTOUT(info, BWI_INFO_BBPPKG_MASK);
6832 	aprint_normal_dev(sc->sc_dev,
6833 	    "BBP id 0x%04x, BBP rev 0x%x, BBP pkg %d\n",
6834 	    sc->sc_bbp_id, sc->sc_bbp_rev, sc->sc_bbp_pkg);
6835 	DPRINTF(sc, BWI_DBG_ATTACH, "nregwin %d, cap 0x%08x\n",
6836 	    nregwin, sc->sc_cap);
6837 
6838 	/*
6839 	 * Create rest of the regwins
6840 	 */
6841 
6842 	/* Don't re-create common regwin, if it is already created */
6843 	i = BWI_REGWIN_EXIST(&sc->sc_com_regwin) ? 1 : 0;
6844 
6845 	for (; i < nregwin; ++i) {
6846 		/*
6847 		 * Get regwin information
6848 		 */
6849 		error = bwi_regwin_select(sc, i);
6850 		if (error) {
6851 			aprint_error_dev(sc->sc_dev, "can't select regwin"
6852 			    " %d\n", i);
6853 			return (error);
6854 		}
6855 		bwi_regwin_info(sc, &rw_type, &rw_rev);
6856 
6857 		/*
6858 		 * Try attach:
6859 		 * 1) Bus (PCI/PCIE) regwin
6860 		 * 2) MAC regwin
6861 		 * Ignore rest types of regwin
6862 		 */
6863 		if (rw_type == BWI_REGWIN_T_BUSPCI ||
6864 		    rw_type == BWI_REGWIN_T_BUSPCIE) {
6865 			if (BWI_REGWIN_EXIST(&sc->sc_bus_regwin)) {
6866 				aprint_error_dev(sc->sc_dev,
6867 				    "bus regwin already exists\n");
6868 			} else {
6869 				BWI_CREATE_REGWIN(&sc->sc_bus_regwin, i,
6870 				    rw_type, rw_rev);
6871 			}
6872 		} else if (rw_type == BWI_REGWIN_T_MAC) {
6873 			/* XXX ignore return value */
6874 			bwi_mac_attach(sc, i, rw_rev);
6875 		}
6876 	}
6877 
6878 	/* At least one MAC shold exist */
6879 	if (!BWI_REGWIN_EXIST(&sc->sc_mac[0].mac_regwin)) {
6880 		aprint_error_dev(sc->sc_dev, "no MAC was found\n");
6881 		return (ENXIO);
6882 	}
6883 	KASSERT(sc->sc_nmac > 0);
6884 
6885 	/* Bus regwin must exist */
6886 	if (!BWI_REGWIN_EXIST(&sc->sc_bus_regwin)) {
6887 		aprint_error_dev(sc->sc_dev, "no bus regwin was found\n");
6888 		return (ENXIO);
6889 	}
6890 
6891 	/* Start with first MAC */
6892 	error = bwi_regwin_switch(sc, &sc->sc_mac[0].mac_regwin, NULL);
6893 	if (error)
6894 		return (error);
6895 
6896 	return (0);
6897 }
6898 
6899 static int
6900 bwi_bus_init(struct bwi_softc *sc, struct bwi_mac *mac)
6901 {
6902 	struct bwi_regwin *old, *bus;
6903 	uint32_t val;
6904 	int error;
6905 
6906 	bus = &sc->sc_bus_regwin;
6907 	KASSERT(sc->sc_cur_regwin == &mac->mac_regwin);
6908 
6909 	/*
6910 	 * Tell bus to generate requested interrupts
6911 	 */
6912 	if (bus->rw_rev < 6 && bus->rw_type == BWI_REGWIN_T_BUSPCI) {
6913 		/*
6914 		 * NOTE: Read BWI_FLAGS from MAC regwin
6915 		 */
6916 		val = CSR_READ_4(sc, BWI_FLAGS);
6917 
6918 		error = bwi_regwin_switch(sc, bus, &old);
6919 		if (error)
6920 			return (error);
6921 
6922 		CSR_SETBITS_4(sc, BWI_INTRVEC, (val & BWI_FLAGS_INTR_MASK));
6923 	} else {
6924 		uint32_t mac_mask;
6925 
6926 		mac_mask = 1 << mac->mac_id;
6927 
6928 		error = bwi_regwin_switch(sc, bus, &old);
6929 		if (error)
6930 			return (error);
6931 
6932 		val = (sc->sc_conf_read)(sc, BWI_PCIR_INTCTL);
6933 		val |= mac_mask << 8;
6934 		(sc->sc_conf_write)(sc, BWI_PCIR_INTCTL, val);
6935 	}
6936 
6937 	if (sc->sc_flags & BWI_F_BUS_INITED)
6938 		goto back;
6939 
6940 	if (bus->rw_type == BWI_REGWIN_T_BUSPCI) {
6941 		/*
6942 		 * Enable prefetch and burst
6943 		 */
6944 		CSR_SETBITS_4(sc, BWI_BUS_CONFIG,
6945 		    BWI_BUS_CONFIG_PREFETCH | BWI_BUS_CONFIG_BURST);
6946 
6947 		if (bus->rw_rev < 5) {
6948 			struct bwi_regwin *com = &sc->sc_com_regwin;
6949 
6950 			/*
6951 			 * Configure timeouts for bus operation
6952 			 */
6953 
6954 			/*
6955 			 * Set service timeout and request timeout
6956 			 */
6957 			CSR_SETBITS_4(sc, BWI_CONF_LO,
6958 			    __SHIFTIN(BWI_CONF_LO_SERVTO,
6959 				BWI_CONF_LO_SERVTO_MASK) |
6960 			    __SHIFTIN(BWI_CONF_LO_REQTO,
6961 				BWI_CONF_LO_REQTO_MASK));
6962 
6963 			/*
6964 			 * If there is common regwin, we switch to that regwin
6965 			 * and switch back to bus regwin once we have done.
6966 			 */
6967 			if (BWI_REGWIN_EXIST(com)) {
6968 				error = bwi_regwin_switch(sc, com, NULL);
6969 				if (error)
6970 					return (error);
6971 			}
6972 
6973 			/* Let bus know what we have changed */
6974 			CSR_WRITE_4(sc, BWI_BUS_ADDR, BWI_BUS_ADDR_MAGIC);
6975 			CSR_READ_4(sc, BWI_BUS_ADDR); /* Flush */
6976 			CSR_WRITE_4(sc, BWI_BUS_DATA, 0);
6977 			CSR_READ_4(sc, BWI_BUS_DATA); /* Flush */
6978 
6979 			if (BWI_REGWIN_EXIST(com)) {
6980 				error = bwi_regwin_switch(sc, bus, NULL);
6981 				if (error)
6982 					return (error);
6983 			}
6984 		} else if (bus->rw_rev >= 11) {
6985 			/*
6986 			 * Enable memory read multiple
6987 			 */
6988 			CSR_SETBITS_4(sc, BWI_BUS_CONFIG, BWI_BUS_CONFIG_MRM);
6989 		}
6990 	} else {
6991 		/* TODO: PCIE */
6992 	}
6993 
6994 	sc->sc_flags |= BWI_F_BUS_INITED;
6995 back:
6996 	return (bwi_regwin_switch(sc, old, NULL));
6997 }
6998 
6999 static void
7000 bwi_get_card_flags(struct bwi_softc *sc)
7001 {
7002 	sc->sc_card_flags = bwi_read_sprom(sc, BWI_SPROM_CARD_FLAGS);
7003 	if (sc->sc_card_flags == 0xffff)
7004 		sc->sc_card_flags = 0;
7005 
7006 	if (sc->sc_pci_subvid == PCI_VENDOR_APPLE &&
7007 	    sc->sc_pci_subdid == 0x4e && /* XXX */
7008 	    sc->sc_pci_revid > 0x40)
7009 		sc->sc_card_flags |= BWI_CARD_F_PA_GPIO9;
7010 
7011 	DPRINTF(sc, BWI_DBG_ATTACH, "card flags 0x%04x\n", sc->sc_card_flags);
7012 }
7013 
7014 static void
7015 bwi_get_eaddr(struct bwi_softc *sc, uint16_t eaddr_ofs, uint8_t *eaddr)
7016 {
7017 	int i;
7018 
7019 	for (i = 0; i < 3; ++i) {
7020 		*((uint16_t *)eaddr + i) =
7021 		    htobe16(bwi_read_sprom(sc, eaddr_ofs + 2 * i));
7022 	}
7023 }
7024 
7025 static void
7026 bwi_get_clock_freq(struct bwi_softc *sc, struct bwi_clock_freq *freq)
7027 {
7028 	struct bwi_regwin *com;
7029 	uint32_t val;
7030 	uint div;
7031 	int src;
7032 
7033 	memset(freq, 0, sizeof(*freq));
7034 	com = &sc->sc_com_regwin;
7035 
7036 	KASSERT(BWI_REGWIN_EXIST(com));
7037 	KASSERT(sc->sc_cur_regwin == com);
7038 	KASSERT(sc->sc_cap & BWI_CAP_CLKMODE);
7039 
7040 	/*
7041 	 * Calculate clock frequency
7042 	 */
7043 	src = -1;
7044 	div = 0;
7045 	if (com->rw_rev < 6) {
7046 		val = (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_OUT);
7047 		if (val & BWI_PCIM_GPIO_OUT_CLKSRC) {
7048 			src = BWI_CLKSRC_PCI;
7049 			div = 64;
7050 		} else {
7051 			src = BWI_CLKSRC_CS_OSC;
7052 			div = 32;
7053 		}
7054 	} else if (com->rw_rev < 10) {
7055 		val = CSR_READ_4(sc, BWI_CLOCK_CTRL);
7056 
7057 		src = __SHIFTOUT(val, BWI_CLOCK_CTRL_CLKSRC);
7058 		if (src == BWI_CLKSRC_LP_OSC)
7059 			div = 1;
7060 		else {
7061 			div = (__SHIFTOUT(val, BWI_CLOCK_CTRL_FDIV) + 1) << 2;
7062 
7063 			/* Unknown source */
7064 			if (src >= BWI_CLKSRC_MAX)
7065 				src = BWI_CLKSRC_CS_OSC;
7066 		}
7067 	} else {
7068 		val = CSR_READ_4(sc, BWI_CLOCK_INFO);
7069 
7070 		src = BWI_CLKSRC_CS_OSC;
7071 		div = (__SHIFTOUT(val, BWI_CLOCK_INFO_FDIV) + 1) << 2;
7072 	}
7073 
7074 	KASSERT(src >= 0 && src < BWI_CLKSRC_MAX);
7075 	KASSERT(div != 0);
7076 
7077 	DPRINTF(sc, BWI_DBG_ATTACH, "clksrc %s\n",
7078 	    src == BWI_CLKSRC_PCI ? "PCI" :
7079 	    (src == BWI_CLKSRC_LP_OSC ? "LP_OSC" : "CS_OSC"));
7080 
7081 	freq->clkfreq_min = bwi_clkfreq[src].freq_min / div;
7082 	freq->clkfreq_max = bwi_clkfreq[src].freq_max / div;
7083 
7084 	DPRINTF(sc, BWI_DBG_ATTACH, "clkfreq min %u, max %u\n",
7085 	    freq->clkfreq_min, freq->clkfreq_max);
7086 }
7087 
7088 static int
7089 bwi_set_clock_mode(struct bwi_softc *sc, enum bwi_clock_mode clk_mode)
7090 {
7091 	struct bwi_regwin *old, *com;
7092 	uint32_t clk_ctrl, clk_src;
7093 	int error, pwr_off = 0;
7094 
7095 	com = &sc->sc_com_regwin;
7096 	if (!BWI_REGWIN_EXIST(com))
7097 		return (0);
7098 
7099 	if (com->rw_rev >= 10 || com->rw_rev < 6)
7100 		return (0);
7101 
7102 	/*
7103 	 * For common regwin whose rev is [6, 10), the chip
7104 	 * must be capable to change clock mode.
7105 	 */
7106 	if ((sc->sc_cap & BWI_CAP_CLKMODE) == 0)
7107 		return (0);
7108 
7109 	error = bwi_regwin_switch(sc, com, &old);
7110 	if (error)
7111 		return (error);
7112 
7113 	if (clk_mode == BWI_CLOCK_MODE_FAST)
7114 		bwi_power_on(sc, 0);	/* Don't turn on PLL */
7115 
7116 	clk_ctrl = CSR_READ_4(sc, BWI_CLOCK_CTRL);
7117 	clk_src = __SHIFTOUT(clk_ctrl, BWI_CLOCK_CTRL_CLKSRC);
7118 
7119 	switch (clk_mode) {
7120 	case BWI_CLOCK_MODE_FAST:
7121 		clk_ctrl &= ~BWI_CLOCK_CTRL_SLOW;
7122 		clk_ctrl |= BWI_CLOCK_CTRL_IGNPLL;
7123 		break;
7124 	case BWI_CLOCK_MODE_SLOW:
7125 		clk_ctrl |= BWI_CLOCK_CTRL_SLOW;
7126 		break;
7127 	case BWI_CLOCK_MODE_DYN:
7128 		clk_ctrl &= ~(BWI_CLOCK_CTRL_SLOW |
7129 		    BWI_CLOCK_CTRL_IGNPLL |
7130 		    BWI_CLOCK_CTRL_NODYN);
7131 		if (clk_src != BWI_CLKSRC_CS_OSC) {
7132 			clk_ctrl |= BWI_CLOCK_CTRL_NODYN;
7133 			pwr_off = 1;
7134 		}
7135 		break;
7136 	}
7137 	CSR_WRITE_4(sc, BWI_CLOCK_CTRL, clk_ctrl);
7138 
7139 	if (pwr_off)
7140 		bwi_power_off(sc, 0);	/* Leave PLL as it is */
7141 
7142 	return (bwi_regwin_switch(sc, old, NULL));
7143 }
7144 
7145 static int
7146 bwi_set_clock_delay(struct bwi_softc *sc)
7147 {
7148 	struct bwi_regwin *old, *com;
7149 	int error;
7150 
7151 	com = &sc->sc_com_regwin;
7152 	if (!BWI_REGWIN_EXIST(com))
7153 		return (0);
7154 
7155 	error = bwi_regwin_switch(sc, com, &old);
7156 	if (error)
7157 		return (error);
7158 
7159 	if (sc->sc_bbp_id == BWI_BBPID_BCM4321) {
7160 		if (sc->sc_bbp_rev == 0)
7161 			CSR_WRITE_4(sc, BWI_CONTROL, BWI_CONTROL_MAGIC0);
7162 		else if (sc->sc_bbp_rev == 1)
7163 			CSR_WRITE_4(sc, BWI_CONTROL, BWI_CONTROL_MAGIC1);
7164 	}
7165 
7166 	if (sc->sc_cap & BWI_CAP_CLKMODE) {
7167 		if (com->rw_rev >= 10)
7168 			CSR_FILT_SETBITS_4(sc, BWI_CLOCK_INFO, 0xffff, 0x40000);
7169 		else {
7170 			struct bwi_clock_freq freq;
7171 
7172 			bwi_get_clock_freq(sc, &freq);
7173 			CSR_WRITE_4(sc, BWI_PLL_ON_DELAY,
7174 			    howmany(freq.clkfreq_max * 150, 1000000));
7175 			CSR_WRITE_4(sc, BWI_FREQ_SEL_DELAY,
7176 			    howmany(freq.clkfreq_max * 15, 1000000));
7177 		}
7178 	}
7179 
7180 	return (bwi_regwin_switch(sc, old, NULL));
7181 }
7182 
7183 static int
7184 bwi_init(struct ifnet *ifp)
7185 {
7186 	struct bwi_softc *sc = ifp->if_softc;
7187 
7188 	bwi_init_statechg(sc, 1);
7189 
7190 	return (0);
7191 }
7192 
7193 static void
7194 bwi_init_statechg(struct bwi_softc *sc, int statechg)
7195 {
7196 	struct ieee80211com *ic = &sc->sc_ic;
7197 	struct ifnet *ifp = &sc->sc_if;
7198 	struct bwi_mac *mac;
7199 	int error;
7200 
7201 	DPRINTF(sc, BWI_DBG_MISC, "%s\n", __func__);
7202 
7203 	bwi_stop(ifp, statechg);
7204 
7205 	/* power on cardbus socket */
7206 	if (sc->sc_enable != NULL)
7207 		(sc->sc_enable)(sc, 0);
7208 
7209 	bwi_bbp_power_on(sc, BWI_CLOCK_MODE_FAST);
7210 
7211 	/* TODO: 2 MAC */
7212 
7213 	mac = &sc->sc_mac[0];
7214 	error = bwi_regwin_switch(sc, &mac->mac_regwin, NULL);
7215 	if (error)
7216 		goto back;
7217 
7218 	error = bwi_mac_init(mac);
7219 	if (error)
7220 		goto back;
7221 
7222 	bwi_bbp_power_on(sc, BWI_CLOCK_MODE_DYN);
7223 
7224 	IEEE80211_ADDR_COPY(ic->ic_myaddr, CLLADDR(ifp->if_sadl));
7225 
7226 	bwi_set_bssid(sc, bwi_zero_addr);	/* Clear BSSID */
7227 	bwi_set_addr_filter(sc, BWI_ADDR_FILTER_MYADDR, ic->ic_myaddr);
7228 
7229 	bwi_mac_reset_hwkeys(mac);
7230 
7231 	if ((mac->mac_flags & BWI_MAC_F_HAS_TXSTATS) == 0) {
7232 		int i;
7233 
7234 #define NRETRY	1000
7235 		/*
7236 		 * Drain any possible pending TX status
7237 		 */
7238 		for (i = 0; i < NRETRY; ++i) {
7239 			if ((CSR_READ_4(sc, BWI_TXSTATUS_0) &
7240 			     BWI_TXSTATUS_0_MORE) == 0)
7241 				break;
7242 			CSR_READ_4(sc, BWI_TXSTATUS_1);
7243 		}
7244 		if (i == NRETRY)
7245 			aprint_error_dev(sc->sc_dev,
7246 			    "can't drain TX status\n");
7247 #undef NRETRY
7248 	}
7249 
7250 	if (mac->mac_phy.phy_mode == IEEE80211_MODE_11G)
7251 		bwi_mac_updateslot(mac, 1);
7252 
7253 	/* Start MAC */
7254 	error = bwi_mac_start(mac);
7255 	if (error)
7256 		goto back;
7257 
7258 	/* Enable intrs */
7259 	bwi_enable_intrs(sc, BWI_INIT_INTRS);
7260 
7261 	ifp->if_flags |= IFF_RUNNING;
7262 	ifp->if_flags &= ~IFF_OACTIVE;
7263 
7264 	if (statechg) {
7265 		if (ic->ic_opmode != IEEE80211_M_MONITOR) {
7266 			/* [TRC: XXX OpenBSD omits this conditional.] */
7267 			if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL)
7268 				ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
7269 		} else {
7270 			ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
7271 		}
7272 	} else {
7273 		ieee80211_new_state(ic, ic->ic_state, -1);
7274 	}
7275 
7276 back:
7277 	if (error)
7278 		bwi_stop(ifp, 1);
7279 	else
7280 		/* [TRC: XXX DragonFlyBD uses ifp->if_start(ifp).] */
7281 		bwi_start(ifp);
7282 }
7283 
7284 static int
7285 bwi_ioctl(struct ifnet *ifp, u_long cmd, void *data)
7286 {
7287 	struct bwi_softc *sc = ifp->if_softc;
7288 	struct ieee80211com *ic = &sc->sc_ic;
7289 	int s, error = 0;
7290 
7291 	/* [TRC: XXX Superstitiously cargo-culted from wi(4).] */
7292 	if (!device_is_active(sc->sc_dev))
7293 		return (ENXIO);
7294 
7295 	s = splnet();
7296 
7297 	switch (cmd) {
7298 	case SIOCSIFFLAGS:
7299 		if ((error = ifioctl_common(ifp, cmd, data)) != 0)
7300 			break;
7301 		if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
7302 		    (IFF_UP | IFF_RUNNING)) {
7303 			struct bwi_mac *mac;
7304 			int promisc = -1;
7305 
7306 			KASSERT(sc->sc_cur_regwin->rw_type ==
7307 			    BWI_REGWIN_T_MAC);
7308 			mac = (struct bwi_mac *)sc->sc_cur_regwin;
7309 
7310 			if ((ifp->if_flags & IFF_PROMISC) &&
7311 			    (sc->sc_flags & BWI_F_PROMISC) == 0) {
7312 				promisc = 1;
7313 				sc->sc_flags |= BWI_F_PROMISC;
7314 			} else if ((ifp->if_flags & IFF_PROMISC) == 0 &&
7315 				   (sc->sc_flags & BWI_F_PROMISC)) {
7316 				promisc = 0;
7317 				sc->sc_flags &= ~BWI_F_PROMISC;
7318 			}
7319 
7320 			if (promisc >= 0)
7321 				bwi_mac_set_promisc(mac, promisc);
7322 		}
7323 
7324 		if (ifp->if_flags & IFF_UP) {
7325 			if (!(ifp->if_flags & IFF_RUNNING))
7326 				bwi_init(ifp);
7327 		} else {
7328 			if (ifp->if_flags & IFF_RUNNING)
7329 				bwi_stop(ifp, 1);
7330 		}
7331 		break;
7332 
7333 	case SIOCADDMULTI:
7334 	case SIOCDELMULTI:
7335 		/* [TRC: Several other drivers appear to have this
7336 		   copied & pasted, so I'm following suit.] */
7337 		/* XXX no h/w multicast filter? --dyoung */
7338 		if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) {
7339 			/* setup multicast filter, etc */
7340 			error = 0;
7341 		}
7342 		break;
7343 
7344 	case SIOCS80211CHANNEL:
7345 		/* [TRC: Pilfered from OpenBSD.  No clue whether it works.] */
7346 		/* allow fast channel switching in monitor mode */
7347 		error = ieee80211_ioctl(ic, cmd, data);
7348 		if (error == ENETRESET &&
7349 		    ic->ic_opmode == IEEE80211_M_MONITOR) {
7350 			if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
7351 			    (IFF_UP | IFF_RUNNING)) {
7352 				/* [TRC: XXX ????] */
7353 				ic->ic_bss->ni_chan = ic->ic_ibss_chan;
7354 				ic->ic_curchan = ic->ic_ibss_chan;
7355 				bwi_set_chan(sc, ic->ic_bss->ni_chan);
7356 			}
7357 			error = 0;
7358 		}
7359 		break;
7360 
7361 	default:
7362 		error = ieee80211_ioctl(ic, cmd, data);
7363 		break;
7364 	}
7365 
7366 	if (error == ENETRESET) {
7367 		if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
7368 		    (IFF_UP | IFF_RUNNING) &&
7369 		    /* [TRC: XXX Superstitiously cargo-culted from iwi(4). */
7370 		    (ic->ic_roaming != IEEE80211_ROAMING_MANUAL))
7371 			bwi_init(ifp);
7372 		error = 0;
7373 	}
7374 
7375 	splx(s);
7376 
7377 	return (error);
7378 }
7379 
7380 static void
7381 bwi_start(struct ifnet *ifp)
7382 {
7383 	struct bwi_softc *sc = ifp->if_softc;
7384 	struct ieee80211com *ic = &sc->sc_ic;
7385 	struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING];
7386 	int trans, idx;
7387 
7388 	/* [TRC: XXX I'm not sure under which conditions we're actually
7389 	   supposed to refuse to start, so I'm copying what OpenBSD and
7390 	   DragonFlyBSD do, even if no one else on NetBSD does it. */
7391 	if ((ifp->if_flags & IFF_OACTIVE) ||
7392 	    (ifp->if_flags & IFF_RUNNING) == 0)
7393 		return;
7394 
7395 	trans = 0;
7396 	idx = tbd->tbd_idx;
7397 
7398 	while (tbd->tbd_buf[idx].tb_mbuf == NULL) {
7399 		struct ieee80211_frame *wh;
7400 		struct ieee80211_node *ni;
7401 		struct mbuf *m;
7402 		int mgt_pkt = 0;
7403 
7404 		IF_DEQUEUE(&ic->ic_mgtq, m);
7405 		if (m != NULL) {
7406 			ni = M_GETCTX(m, struct ieee80211_node *);
7407 			M_CLEARCTX(m);
7408 
7409 			mgt_pkt = 1;
7410 		} else {
7411 			struct ether_header *eh;
7412 
7413 			if (ic->ic_state != IEEE80211_S_RUN)
7414 				break;
7415 
7416 			IFQ_DEQUEUE(&ifp->if_snd, m);
7417 			if (m == NULL)
7418 				break;
7419 
7420 			if (m->m_len < sizeof(*eh)) {
7421 				m = m_pullup(m, sizeof(*eh));
7422 				if (m == NULL) {
7423 					if_statinc(ifp, if_oerrors);
7424 					continue;
7425 				}
7426 			}
7427 			eh = mtod(m, struct ether_header *);
7428 
7429 			ni = ieee80211_find_txnode(ic, eh->ether_dhost);
7430 			if (ni == NULL) {
7431 				if_statinc(ifp, if_oerrors);
7432 				m_freem(m);
7433 				continue;
7434 			}
7435 
7436 			/* [TRC: XXX Superstitiously cargo-culted from
7437 			   ath(4) and wi(4).] */
7438 			if ((ni->ni_flags & IEEE80211_NODE_PWR_MGT) &&
7439 			    (m->m_flags & M_PWR_SAV) == 0) {
7440 				ieee80211_pwrsave(ic, ni, m);
7441 				ieee80211_free_node(ni);
7442 				continue;
7443 			}
7444 
7445 			/* [TRC: XXX I *think* we're supposed to do
7446 			   this, but honestly I have no clue.  We don't
7447 			   use M_WME_GETAC, so...] */
7448 			if (ieee80211_classify(ic, m, ni)) {
7449 				/* [TRC: XXX What debug flag?] */
7450 				DPRINTF(sc, BWI_DBG_MISC,
7451 				    "%s: discard, classification failure\n",
7452 				    __func__);
7453 				if_statinc(ifp, if_oerrors);
7454 				m_freem(m);
7455 				ieee80211_free_node(ni);
7456 				continue;
7457 			}
7458 
7459 			/* [TRC: XXX wi(4) and awi(4) do this; iwi(4)
7460 			   doesn't.] */
7461 			if_statinc(ifp, if_opackets);
7462 
7463 			/* [TRC: XXX When should the packet be
7464 			   filtered?  Different drivers appear to do it
7465 			   at different times.] */
7466 			/* TODO: PS */
7467 			bpf_mtap(ifp, m, BPF_D_OUT);
7468 			m = ieee80211_encap(ic, m, ni);
7469 			if (m == NULL) {
7470 				if_statinc(ifp, if_oerrors);
7471 				ieee80211_free_node(ni);
7472 				continue;
7473 			}
7474 		}
7475 		bpf_mtap3(ic->ic_rawbpf, m, BPF_D_OUT);
7476 
7477 		wh = mtod(m, struct ieee80211_frame *);
7478 		/* [TRC: XXX What about ic->ic_flags & IEEE80211_F_PRIVACY?] */
7479 		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
7480 			if (ieee80211_crypto_encap(ic, ni, m) == NULL) {
7481 				if_statinc(ifp, if_oerrors);
7482 				m_freem(m);
7483 				ieee80211_free_node(ni);
7484 				continue;
7485 			}
7486 		}
7487 		wh = NULL;	/* [TRC: XXX Huh?] */
7488 
7489 		if (bwi_encap(sc, idx, m, &ni, mgt_pkt) != 0) {
7490 			/* 'm' is freed in bwi_encap() if we reach here */
7491 			if_statinc(ifp, if_oerrors);
7492 			if (ni != NULL)
7493 				ieee80211_free_node(ni);
7494 			continue;
7495 		}
7496 
7497 		trans = 1;
7498 		tbd->tbd_used++;
7499 		idx = (idx + 1) % BWI_TX_NDESC;
7500 
7501 		if (tbd->tbd_used + BWI_TX_NSPRDESC >= BWI_TX_NDESC) {
7502 			ifp->if_flags |= IFF_OACTIVE;
7503 			break;
7504 		}
7505 	}
7506 	tbd->tbd_idx = idx;
7507 
7508 	if (trans)
7509 		sc->sc_tx_timer = 5;
7510 	ifp->if_timer = 1;
7511 }
7512 
7513 static void
7514 bwi_watchdog(struct ifnet *ifp)
7515 {
7516 	struct bwi_softc *sc = ifp->if_softc;
7517 
7518 	ifp->if_timer = 0;
7519 
7520 	if ((ifp->if_flags & IFF_RUNNING) == 0 ||
7521 	    !device_is_active(sc->sc_dev))
7522 		return;
7523 
7524 	if (sc->sc_tx_timer) {
7525 		if (--sc->sc_tx_timer == 0) {
7526 			aprint_error_dev(sc->sc_dev, "device timeout\n");
7527 			if_statinc(ifp, if_oerrors);
7528 			/* TODO */
7529 			/* [TRC: XXX TODO what?  Stop the device?
7530 			   Bring it down?  iwi(4) does this.] */
7531 		} else
7532 			ifp->if_timer = 1;
7533 	}
7534 
7535 	ieee80211_watchdog(&sc->sc_ic);
7536 }
7537 
7538 static void
7539 bwi_stop(struct ifnet *ifp, int state_chg)
7540 {
7541 	struct bwi_softc *sc = ifp->if_softc;
7542 	struct ieee80211com *ic = &sc->sc_ic;
7543 	struct bwi_mac *mac;
7544 	int i, error, pwr_off = 0;
7545 
7546 	DPRINTF(sc, BWI_DBG_MISC, "%s\n", __func__);
7547 
7548 	if (state_chg)
7549 		ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
7550 	else
7551 		bwi_newstate_begin(sc, IEEE80211_S_INIT);
7552 
7553 	if (ifp->if_flags & IFF_RUNNING) {
7554 		KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
7555 		mac = (struct bwi_mac *)sc->sc_cur_regwin;
7556 
7557 		bwi_disable_intrs(sc, BWI_ALL_INTRS);
7558 		CSR_READ_4(sc, BWI_MAC_INTR_MASK);
7559 		bwi_mac_stop(mac);
7560 	}
7561 
7562 	for (i = 0; i < sc->sc_nmac; ++i) {
7563 		struct bwi_regwin *old_rw;
7564 
7565 		mac = &sc->sc_mac[i];
7566 		if ((mac->mac_flags & BWI_MAC_F_INITED) == 0)
7567 			continue;
7568 
7569 		error = bwi_regwin_switch(sc, &mac->mac_regwin, &old_rw);
7570 		if (error)
7571 			continue;
7572 
7573 		bwi_mac_shutdown(mac);
7574 		pwr_off = 1;
7575 
7576 		bwi_regwin_switch(sc, old_rw, NULL);
7577 	}
7578 
7579 	if (pwr_off)
7580 		bwi_bbp_power_off(sc);
7581 
7582 	sc->sc_tx_timer = 0;
7583 	ifp->if_timer = 0;
7584 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
7585 
7586 	/* power off cardbus socket */
7587 	if (sc->sc_disable != NULL)
7588 		(sc->sc_disable)(sc, 0);
7589 
7590 	return;
7591 }
7592 
7593 static void
7594 bwi_newstate_begin(struct bwi_softc *sc, enum ieee80211_state nstate)
7595 {
7596 	callout_stop(&sc->sc_scan_ch);
7597 	callout_stop(&sc->sc_calib_ch);
7598 
7599 	bwi_led_newstate(sc, nstate);
7600 
7601 	if (nstate == IEEE80211_S_INIT)
7602 		sc->sc_txpwrcb_type = BWI_TXPWR_INIT;
7603 }
7604 
7605 static int
7606 bwi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
7607 {
7608 	struct bwi_softc *sc = ic->ic_ifp->if_softc;
7609 	struct ieee80211_node *ni;
7610 	int error;
7611 
7612 	/* [TRC: XXX amrr] */
7613 	callout_stop(&sc->sc_amrr_ch);
7614 
7615 	bwi_newstate_begin(sc, nstate);
7616 
7617 	if (nstate == IEEE80211_S_INIT)
7618 		goto back;
7619 
7620 	/* [TRC: XXX What channel do we set this to? */
7621 	error = bwi_set_chan(sc, ic->ic_curchan);
7622 	if (error) {
7623 		aprint_error_dev(sc->sc_dev, "can't set channel to %u\n",
7624 		    ieee80211_chan2ieee(ic, ic->ic_curchan));
7625 		return (error);
7626 	}
7627 
7628 	if (ic->ic_opmode == IEEE80211_M_MONITOR) {
7629 		/* Nothing to do */
7630 	} else if (nstate == IEEE80211_S_RUN) {
7631 		struct bwi_mac *mac;
7632 
7633 		ni = ic->ic_bss;
7634 
7635 		bwi_set_bssid(sc, ic->ic_bss->ni_bssid);
7636 
7637 		KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
7638 		mac = (struct bwi_mac *)sc->sc_cur_regwin;
7639 
7640 		/* Initial TX power calibration */
7641 		bwi_mac_calibrate_txpower(mac, BWI_TXPWR_INIT);
7642 #ifdef notyet
7643 		sc->sc_txpwrcb_type = BWI_TXPWR_FORCE;
7644 #else
7645 		sc->sc_txpwrcb_type = BWI_TXPWR_CALIB;
7646 #endif
7647 		/* [TRC: XXX amrr] */
7648 		if (ic->ic_opmode == IEEE80211_M_STA) {
7649 			/* fake a join to init the tx rate */
7650 			bwi_newassoc(ni, 1);
7651 		}
7652 
7653 		if (ic->ic_opmode != IEEE80211_M_MONITOR) {
7654 			/* start automatic rate control timer */
7655 			if (ic->ic_fixed_rate == -1)
7656 				callout_schedule(&sc->sc_amrr_ch, hz / 2);
7657 		}
7658 	} else
7659 		bwi_set_bssid(sc, bwi_zero_addr);
7660 
7661 back:
7662 	error = (sc->sc_newstate)(ic, nstate, arg);
7663 
7664 	if (nstate == IEEE80211_S_SCAN) {
7665 		callout_schedule(&sc->sc_scan_ch,
7666 		    (sc->sc_dwell_time * hz) / 1000);
7667 	} else if (nstate == IEEE80211_S_RUN) {
7668 		/* XXX 15 seconds */
7669 		callout_schedule(&sc->sc_calib_ch, hz);
7670 	}
7671 
7672 	return (error);
7673 }
7674 
7675 static int
7676 bwi_media_change(struct ifnet *ifp)
7677 {
7678 	int error;
7679 
7680 	error = ieee80211_media_change(ifp);
7681 	if (error != ENETRESET)
7682 		return (error);
7683 
7684 	if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
7685 		bwi_init(ifp);
7686 
7687 	return (0);
7688 }
7689 
7690 /* [TRC: XXX amrr] */
7691 static void
7692 bwi_iter_func(void *arg, struct ieee80211_node *ni)
7693 {
7694 	struct bwi_softc *sc = arg;
7695 	struct bwi_node *bn = (struct bwi_node *)ni;
7696 
7697 	ieee80211_amrr_choose(&sc->sc_amrr, ni, &bn->amn);
7698 }
7699 
7700 static void
7701 bwi_amrr_timeout(void *arg)
7702 {
7703 	struct bwi_softc *sc = arg;
7704 	struct ieee80211com *ic = &sc->sc_ic;
7705 	int s;
7706 
7707 	s = splnet();
7708 	if (ic->ic_opmode == IEEE80211_M_STA)
7709 		bwi_iter_func(sc, ic->ic_bss);
7710 	else
7711 		/* [TRC: XXX I'm making a wild guess about what to
7712 		   supply for the node table.] */
7713 		ieee80211_iterate_nodes(&ic->ic_sta, bwi_iter_func, sc);
7714 
7715 	callout_schedule(&sc->sc_amrr_ch, hz / 2);
7716 	splx(s);
7717 }
7718 
7719 static void
7720 bwi_newassoc(struct ieee80211_node *ni, int isnew)
7721 {
7722 	struct ieee80211com *ic = ni->ni_ic;
7723 	struct bwi_softc *sc = ic->ic_ifp->if_softc;
7724 	int i;
7725 
7726 	DPRINTF(sc, BWI_DBG_STATION, "%s\n", __func__);
7727 
7728 	ieee80211_amrr_node_init(&sc->sc_amrr, &((struct bwi_node *)ni)->amn);
7729 
7730 	/* set rate to some reasonable initial value */
7731 	for (i = ni->ni_rates.rs_nrates - 1;
7732 	    i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL) > 72;
7733 	    i--);
7734 
7735 	ni->ni_txrate = i;
7736 }
7737 
7738 static struct ieee80211_node *
7739 bwi_node_alloc(struct ieee80211_node_table *nt)
7740 {
7741 	struct bwi_node *bn;
7742 
7743 	bn = malloc(sizeof(struct bwi_node), M_80211_NODE, M_NOWAIT | M_ZERO);
7744 
7745 	return ((struct ieee80211_node *)bn);
7746 }
7747 /* [TRC: XXX amrr end] */
7748 
7749 static int
7750 bwi_dma_alloc(struct bwi_softc *sc)
7751 {
7752 	int error, i, has_txstats;
7753 	/* [TRC: XXX DragonFlyBSD adjusts the low address for different
7754 	   bus spaces.  Should we?] */
7755 	bus_size_t tx_ring_sz, rx_ring_sz, desc_sz = 0;
7756 	uint32_t txrx_ctrl_step = 0;
7757 
7758 	has_txstats = 0;
7759 	for (i = 0; i < sc->sc_nmac; ++i) {
7760 		if (sc->sc_mac[i].mac_flags & BWI_MAC_F_HAS_TXSTATS) {
7761 			has_txstats = 1;
7762 			break;
7763 		}
7764 	}
7765 
7766 	switch (sc->sc_bus_space) {
7767 	case BWI_BUS_SPACE_30BIT:
7768 	case BWI_BUS_SPACE_32BIT:
7769 		desc_sz = sizeof(struct bwi_desc32);
7770 		txrx_ctrl_step = 0x20;
7771 
7772 		sc->sc_init_tx_ring = bwi_init_tx_ring32;
7773 		sc->sc_free_tx_ring = bwi_free_tx_ring32;
7774 		sc->sc_init_rx_ring = bwi_init_rx_ring32;
7775 		sc->sc_free_rx_ring = bwi_free_rx_ring32;
7776 		sc->sc_setup_rxdesc = bwi_setup_rx_desc32;
7777 		sc->sc_setup_txdesc = bwi_setup_tx_desc32;
7778 		sc->sc_rxeof = bwi_rxeof32;
7779 		sc->sc_start_tx = bwi_start_tx32;
7780 		if (has_txstats) {
7781 			sc->sc_init_txstats = bwi_init_txstats32;
7782 			sc->sc_free_txstats = bwi_free_txstats32;
7783 			sc->sc_txeof_status = bwi_txeof_status32;
7784 		}
7785 		break;
7786 
7787 	case BWI_BUS_SPACE_64BIT:
7788 		desc_sz = sizeof(struct bwi_desc64);
7789 		txrx_ctrl_step = 0x40;
7790 
7791 		sc->sc_init_tx_ring = bwi_init_tx_ring64;
7792 		sc->sc_free_tx_ring = bwi_free_tx_ring64;
7793 		sc->sc_init_rx_ring = bwi_init_rx_ring64;
7794 		sc->sc_free_rx_ring = bwi_free_rx_ring64;
7795 		sc->sc_setup_rxdesc = bwi_setup_rx_desc64;
7796 		sc->sc_setup_txdesc = bwi_setup_tx_desc64;
7797 		sc->sc_rxeof = bwi_rxeof64;
7798 		sc->sc_start_tx = bwi_start_tx64;
7799 		if (has_txstats) {
7800 			sc->sc_init_txstats = bwi_init_txstats64;
7801 			sc->sc_free_txstats = bwi_free_txstats64;
7802 			sc->sc_txeof_status = bwi_txeof_status64;
7803 		}
7804 		break;
7805 	}
7806 
7807 	KASSERT(desc_sz != 0);
7808 	KASSERT(txrx_ctrl_step != 0);
7809 
7810 	tx_ring_sz = roundup(desc_sz * BWI_TX_NDESC, BWI_RING_ALIGN);
7811 	rx_ring_sz = roundup(desc_sz * BWI_RX_NDESC, BWI_RING_ALIGN);
7812 
7813 	/* [TRC: XXX Using OpenBSD's code, which is rather different
7814 	   from DragonFlyBSD's.] */
7815 #define TXRX_CTRL(idx)	(BWI_TXRX_CTRL_BASE + (idx) * txrx_ctrl_step)
7816 	/*
7817 	 * Create TX ring DMA stuffs
7818 	 */
7819 	for (i = 0; i < BWI_TX_NRING; ++i) {
7820 		error = bus_dmamap_create(sc->sc_dmat, tx_ring_sz, 1,
7821 		    tx_ring_sz, 0, BUS_DMA_NOWAIT,
7822 		    &sc->sc_tx_rdata[i].rdata_dmap);
7823 		if (error) {
7824 			aprint_error_dev(sc->sc_dev,
7825 			    "%dth TX ring DMA create failed\n", i);
7826 			return (error);
7827 		}
7828 		error = bwi_dma_ring_alloc(sc,
7829 		    &sc->sc_tx_rdata[i], tx_ring_sz, TXRX_CTRL(i));
7830 		if (error) {
7831 			aprint_error_dev(sc->sc_dev,
7832 			    "%dth TX ring DMA alloc failed\n", i);
7833 			return (error);
7834 		}
7835 	}
7836 
7837 	/*
7838 	 * Create RX ring DMA stuffs
7839 	 */
7840 	error = bus_dmamap_create(sc->sc_dmat, rx_ring_sz, 1,
7841 	    rx_ring_sz, 0, BUS_DMA_NOWAIT,
7842 	    &sc->sc_rx_rdata.rdata_dmap);
7843 	if (error) {
7844 		aprint_error_dev(sc->sc_dev, "RX ring DMA create failed\n");
7845 		return (error);
7846 	}
7847 
7848 	error = bwi_dma_ring_alloc(sc, &sc->sc_rx_rdata,
7849 	    rx_ring_sz, TXRX_CTRL(0));
7850 	if (error) {
7851 		aprint_error_dev(sc->sc_dev, "RX ring DMA alloc failed\n");
7852 		return (error);
7853 	}
7854 
7855 	if (has_txstats) {
7856 		error = bwi_dma_txstats_alloc(sc, TXRX_CTRL(3), desc_sz);
7857 		if (error) {
7858 			aprint_error_dev(sc->sc_dev,
7859 			    "TX stats DMA alloc failed\n");
7860 			return (error);
7861 		}
7862 	}
7863 #undef TXRX_CTRL
7864 
7865 	return (bwi_dma_mbuf_create(sc));
7866 }
7867 
7868 static void
7869 bwi_dma_free(struct bwi_softc *sc)
7870 {
7871 	int i;
7872 
7873 	for (i = 0; i < BWI_TX_NRING; ++i)
7874 		bwi_ring_data_free(&sc->sc_tx_rdata[i], sc);
7875 
7876 	bwi_ring_data_free(&sc->sc_rx_rdata, sc);
7877 	bwi_dma_txstats_free(sc);
7878 	bwi_dma_mbuf_destroy(sc, BWI_TX_NRING, 1);
7879 }
7880 
7881 static void
7882 bwi_ring_data_free(struct bwi_ring_data *rd, struct bwi_softc *sc)
7883 {
7884 	if (rd->rdata_desc != NULL) {
7885 		bus_dmamap_unload(sc->sc_dmat, rd->rdata_dmap);
7886 		bus_dmamem_free(sc->sc_dmat, &rd->rdata_seg, 1);
7887 	}
7888 }
7889 
7890 static int
7891 bwi_dma_ring_alloc(struct bwi_softc *sc,
7892     struct bwi_ring_data *rd, bus_size_t size, uint32_t txrx_ctrl)
7893 {
7894 	int error, nsegs;
7895 
7896 	error = bus_dmamem_alloc(sc->sc_dmat, size, BWI_ALIGN, 0,
7897 	    &rd->rdata_seg, 1, &nsegs, BUS_DMA_NOWAIT);
7898 	if (error) {
7899 		aprint_error_dev(sc->sc_dev, "can't allocate DMA mem\n");
7900 		return (error);
7901 	}
7902 
7903 	error = bus_dmamem_map(sc->sc_dmat, &rd->rdata_seg, nsegs,
7904 	    size, (void **)&rd->rdata_desc, BUS_DMA_NOWAIT);
7905 	if (error) {
7906 		aprint_error_dev(sc->sc_dev, "can't map DMA mem\n");
7907 		return (error);
7908 	}
7909 
7910 	error = bus_dmamap_load(sc->sc_dmat, rd->rdata_dmap, rd->rdata_desc,
7911 	    size, NULL, BUS_DMA_WAITOK);
7912 	if (error) {
7913 		aprint_error_dev(sc->sc_dev, "can't load DMA mem\n");
7914 		bus_dmamem_free(sc->sc_dmat, &rd->rdata_seg, nsegs);
7915 		rd->rdata_desc = NULL;
7916 		return (error);
7917 	}
7918 
7919 	rd->rdata_paddr = rd->rdata_dmap->dm_segs[0].ds_addr;
7920 	rd->rdata_txrx_ctrl = txrx_ctrl;
7921 
7922 	return (0);
7923 }
7924 
7925 static int
7926 bwi_dma_txstats_alloc(struct bwi_softc *sc, uint32_t ctrl_base,
7927     bus_size_t desc_sz)
7928 {
7929 	struct bwi_txstats_data *st;
7930 	bus_size_t dma_size;
7931 	int error, nsegs;
7932 
7933 	st = malloc(sizeof(*st), M_DEVBUF, M_WAITOK | M_ZERO);
7934 	sc->sc_txstats = st;
7935 
7936 	/*
7937 	 * Create TX stats descriptor DMA stuffs
7938 	 */
7939 	dma_size = roundup(desc_sz * BWI_TXSTATS_NDESC, BWI_RING_ALIGN);
7940 
7941 	error = bus_dmamap_create(sc->sc_dmat, dma_size, 1, dma_size, 0,
7942 	    BUS_DMA_NOWAIT, &st->stats_ring_dmap);
7943 	if (error) {
7944 		aprint_error_dev(sc->sc_dev,
7945 		    "can't create txstats ring DMA mem\n");
7946 		return (error);
7947 	}
7948 
7949 	error = bus_dmamem_alloc(sc->sc_dmat, dma_size, BWI_RING_ALIGN, 0,
7950 	     &st->stats_ring_seg, 1, &nsegs, BUS_DMA_NOWAIT);
7951 	if (error) {
7952 		aprint_error_dev(sc->sc_dev,
7953 		    "can't allocate txstats ring DMA mem\n");
7954 		return (error);
7955 	}
7956 
7957 	error = bus_dmamem_map(sc->sc_dmat, &st->stats_ring_seg, nsegs,
7958 	    dma_size, (void **)&st->stats_ring, BUS_DMA_NOWAIT);
7959 	if (error) {
7960 		aprint_error_dev(sc->sc_dev,
7961 		    "can't map txstats ring DMA mem\n");
7962 		return (error);
7963 	}
7964 
7965 	error = bus_dmamap_load(sc->sc_dmat, st->stats_ring_dmap,
7966 	    st->stats_ring, dma_size, NULL, BUS_DMA_WAITOK);
7967 	if (error) {
7968 		aprint_error_dev(sc->sc_dev,
7969 		    "can't load txstats ring DMA mem\n");
7970 		bus_dmamem_free(sc->sc_dmat, &st->stats_ring_seg, nsegs);
7971 		return (error);
7972 	}
7973 
7974 	memset(st->stats_ring, 0, dma_size);
7975 	st->stats_ring_paddr = st->stats_ring_dmap->dm_segs[0].ds_addr;
7976 
7977 	/*
7978 	 * Create TX stats DMA stuffs
7979 	 */
7980 	dma_size = roundup(sizeof(struct bwi_txstats) * BWI_TXSTATS_NDESC,
7981 	    BWI_ALIGN);
7982 
7983 	error = bus_dmamap_create(sc->sc_dmat, dma_size, 1, dma_size, 0,
7984 	    BUS_DMA_NOWAIT, &st->stats_dmap);
7985 	if (error) {
7986 		aprint_error_dev(sc->sc_dev,
7987 		    "can't create txstats ring DMA mem\n");
7988 		return (error);
7989 	}
7990 
7991 	error = bus_dmamem_alloc(sc->sc_dmat, dma_size, BWI_ALIGN, 0,
7992 	    &st->stats_seg, 1, &nsegs, BUS_DMA_NOWAIT);
7993 	if (error) {
7994 		aprint_error_dev(sc->sc_dev,
7995 		    "can't allocate txstats DMA mem\n");
7996 		return (error);
7997 	}
7998 
7999 	error = bus_dmamem_map(sc->sc_dmat, &st->stats_seg, nsegs,
8000 	    dma_size, (void **)&st->stats, BUS_DMA_NOWAIT);
8001 	if (error) {
8002 		aprint_error_dev(sc->sc_dev, "can't map txstats DMA mem\n");
8003 		return (error);
8004 	}
8005 
8006 	error = bus_dmamap_load(sc->sc_dmat, st->stats_dmap, st->stats,
8007 	    dma_size, NULL, BUS_DMA_WAITOK);
8008 	if (error) {
8009 		aprint_error_dev(sc->sc_dev, "can't load txstats DMA mem\n");
8010 		bus_dmamem_free(sc->sc_dmat, &st->stats_seg, nsegs);
8011 		return (error);
8012 	}
8013 
8014 	memset(st->stats, 0, dma_size);
8015 	st->stats_paddr = st->stats_dmap->dm_segs[0].ds_addr;
8016 	st->stats_ctrl_base = ctrl_base;
8017 
8018 	return (0);
8019 }
8020 
8021 static void
8022 bwi_dma_txstats_free(struct bwi_softc *sc)
8023 {
8024 	struct bwi_txstats_data *st;
8025 
8026 	if (sc->sc_txstats == NULL)
8027 		return;
8028 	st = sc->sc_txstats;
8029 
8030 	bus_dmamap_unload(sc->sc_dmat, st->stats_ring_dmap);
8031 	bus_dmamem_free(sc->sc_dmat, &st->stats_ring_seg, 1);
8032 
8033 	bus_dmamap_unload(sc->sc_dmat, st->stats_dmap);
8034 	bus_dmamem_free(sc->sc_dmat, &st->stats_seg, 1);
8035 
8036 	free(st, M_DEVBUF);
8037 }
8038 
8039 static int
8040 bwi_dma_mbuf_create(struct bwi_softc *sc)
8041 {
8042 	struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata;
8043 	int i, j, k, ntx, error;
8044 
8045 	ntx = 0;
8046 
8047 	/*
8048 	 * Create TX mbuf DMA map
8049 	 */
8050 	for (i = 0; i < BWI_TX_NRING; ++i) {
8051 		struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[i];
8052 
8053 		for (j = 0; j < BWI_TX_NDESC; ++j) {
8054 			error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES,
8055 			    0, BUS_DMA_NOWAIT, &tbd->tbd_buf[j].tb_dmap);
8056 			if (error) {
8057 				aprint_error_dev(sc->sc_dev,
8058 				    "can't create %dth tbd, %dth DMA map\n",
8059 				    i, j);
8060 				ntx = i;
8061 				for (k = 0; k < j; ++k) {
8062 					bus_dmamap_destroy(sc->sc_dmat,
8063 					    tbd->tbd_buf[k].tb_dmap);
8064 				}
8065 				goto fail;
8066 			}
8067 		}
8068 	}
8069 	ntx = BWI_TX_NRING;
8070 
8071 	/*
8072 	 * Create RX mbuf DMA map and a spare DMA map
8073 	 */
8074 	error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0,
8075 	    BUS_DMA_NOWAIT, &rbd->rbd_tmp_dmap);
8076 	if (error) {
8077 		aprint_error_dev(sc->sc_dev,
8078 		    "can't create spare RX buf DMA map\n");
8079 		goto fail;
8080 	}
8081 
8082 	for (j = 0; j < BWI_RX_NDESC; ++j) {
8083 		error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0,
8084 		    BUS_DMA_NOWAIT, &rbd->rbd_buf[j].rb_dmap);
8085 		if (error) {
8086 			aprint_error_dev(sc->sc_dev,
8087 			    "can't create %dth RX buf DMA map\n", j);
8088 
8089 			for (k = 0; k < j; ++k) {
8090 				bus_dmamap_destroy(sc->sc_dmat,
8091 				    rbd->rbd_buf[j].rb_dmap);
8092 			}
8093 			bus_dmamap_destroy(sc->sc_dmat,
8094 			    rbd->rbd_tmp_dmap);
8095 			goto fail;
8096 		}
8097 	}
8098 
8099 	return (0);
8100 fail:
8101 	bwi_dma_mbuf_destroy(sc, ntx, 0);
8102 
8103 	return (error);
8104 }
8105 
8106 static void
8107 bwi_dma_mbuf_destroy(struct bwi_softc *sc, int ntx, int nrx)
8108 {
8109 	int i, j;
8110 
8111 	for (i = 0; i < ntx; ++i) {
8112 		struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[i];
8113 
8114 		for (j = 0; j < BWI_TX_NDESC; ++j) {
8115 			struct bwi_txbuf *tb = &tbd->tbd_buf[j];
8116 
8117 			if (tb->tb_mbuf != NULL) {
8118 				bus_dmamap_unload(sc->sc_dmat,
8119 				    tb->tb_dmap);
8120 				m_freem(tb->tb_mbuf);
8121 			}
8122 			if (tb->tb_ni != NULL)
8123 				ieee80211_free_node(tb->tb_ni);
8124 			bus_dmamap_destroy(sc->sc_dmat, tb->tb_dmap);
8125 		}
8126 	}
8127 
8128 	if (nrx) {
8129 		struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata;
8130 
8131 		bus_dmamap_destroy(sc->sc_dmat, rbd->rbd_tmp_dmap);
8132 		for (j = 0; j < BWI_RX_NDESC; ++j) {
8133 			struct bwi_rxbuf *rb = &rbd->rbd_buf[j];
8134 
8135 			if (rb->rb_mbuf != NULL) {
8136 				bus_dmamap_unload(sc->sc_dmat,
8137 						  rb->rb_dmap);
8138 				m_freem(rb->rb_mbuf);
8139 			}
8140 			bus_dmamap_destroy(sc->sc_dmat, rb->rb_dmap);
8141 		}
8142 	}
8143 }
8144 
8145 static void
8146 bwi_enable_intrs(struct bwi_softc *sc, uint32_t enable_intrs)
8147 {
8148 	CSR_SETBITS_4(sc, BWI_MAC_INTR_MASK, enable_intrs);
8149 }
8150 
8151 static void
8152 bwi_disable_intrs(struct bwi_softc *sc, uint32_t disable_intrs)
8153 {
8154 	CSR_CLRBITS_4(sc, BWI_MAC_INTR_MASK, disable_intrs);
8155 }
8156 
8157 static int
8158 bwi_init_tx_ring32(struct bwi_softc *sc, int ring_idx)
8159 {
8160 	struct bwi_ring_data *rd;
8161 	struct bwi_txbuf_data *tbd;
8162 	uint32_t val, addr_hi, addr_lo;
8163 
8164 	KASSERT(ring_idx < BWI_TX_NRING);
8165 	rd = &sc->sc_tx_rdata[ring_idx];
8166 	tbd = &sc->sc_tx_bdata[ring_idx];
8167 
8168 	tbd->tbd_idx = 0;
8169 	tbd->tbd_used = 0;
8170 
8171 	memset(rd->rdata_desc, 0, sizeof(struct bwi_desc32) * BWI_TX_NDESC);
8172 	bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0,
8173 	    rd->rdata_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
8174 
8175 	addr_lo = __SHIFTOUT(rd->rdata_paddr, BWI_TXRX32_RINGINFO_ADDR_MASK);
8176 	addr_hi = __SHIFTOUT(rd->rdata_paddr, BWI_TXRX32_RINGINFO_FUNC_MASK);
8177 
8178 	val = __SHIFTIN(addr_lo, BWI_TXRX32_RINGINFO_ADDR_MASK) |
8179 	    __SHIFTIN(BWI_TXRX32_RINGINFO_FUNC_TXRX,
8180 	    BWI_TXRX32_RINGINFO_FUNC_MASK);
8181 	CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_RINGINFO, val);
8182 
8183 	val = __SHIFTIN(addr_hi, BWI_TXRX32_CTRL_ADDRHI_MASK) |
8184 	      BWI_TXRX32_CTRL_ENABLE;
8185 	CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_CTRL, val);
8186 
8187 	return (0);
8188 }
8189 
8190 static void
8191 bwi_init_rxdesc_ring32(struct bwi_softc *sc, uint32_t ctrl_base,
8192     bus_addr_t paddr, int hdr_size, int ndesc)
8193 {
8194 	uint32_t val, addr_hi, addr_lo;
8195 
8196 	addr_lo = __SHIFTOUT(paddr, BWI_TXRX32_RINGINFO_ADDR_MASK);
8197 	addr_hi = __SHIFTOUT(paddr, BWI_TXRX32_RINGINFO_FUNC_MASK);
8198 
8199 	val = __SHIFTIN(addr_lo, BWI_TXRX32_RINGINFO_ADDR_MASK) |
8200 	    __SHIFTIN(BWI_TXRX32_RINGINFO_FUNC_TXRX,
8201 	      		BWI_TXRX32_RINGINFO_FUNC_MASK);
8202 	CSR_WRITE_4(sc, ctrl_base + BWI_RX32_RINGINFO, val);
8203 
8204 	val = __SHIFTIN(hdr_size, BWI_RX32_CTRL_HDRSZ_MASK) |
8205 	    __SHIFTIN(addr_hi, BWI_TXRX32_CTRL_ADDRHI_MASK) |
8206 	    BWI_TXRX32_CTRL_ENABLE;
8207 	CSR_WRITE_4(sc, ctrl_base + BWI_RX32_CTRL, val);
8208 
8209 	CSR_WRITE_4(sc, ctrl_base + BWI_RX32_INDEX,
8210 	    (ndesc - 1) * sizeof(struct bwi_desc32));
8211 }
8212 
8213 static int
8214 bwi_init_rx_ring32(struct bwi_softc *sc)
8215 {
8216 	struct bwi_ring_data *rd = &sc->sc_rx_rdata;
8217 	int i, error;
8218 
8219 	sc->sc_rx_bdata.rbd_idx = 0;
8220 
8221 	for (i = 0; i < BWI_RX_NDESC; ++i) {
8222 		error = bwi_newbuf(sc, i, 1);
8223 		if (error) {
8224 			aprint_error_dev(sc->sc_dev,
8225 			    "can't allocate %dth RX buffer\n", i);
8226 			return (error);
8227 		}
8228 	}
8229 	bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0,
8230 	    rd->rdata_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
8231 
8232 	bwi_init_rxdesc_ring32(sc, rd->rdata_txrx_ctrl, rd->rdata_paddr,
8233 	    sizeof(struct bwi_rxbuf_hdr), BWI_RX_NDESC);
8234 	return (0);
8235 }
8236 
8237 static int
8238 bwi_init_txstats32(struct bwi_softc *sc)
8239 {
8240 	struct bwi_txstats_data *st = sc->sc_txstats;
8241 	bus_addr_t stats_paddr;
8242 	int i;
8243 
8244 	memset(st->stats, 0, BWI_TXSTATS_NDESC * sizeof(struct bwi_txstats));
8245 	bus_dmamap_sync(sc->sc_dmat, st->stats_dmap, 0,
8246 	    st->stats_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
8247 
8248 	st->stats_idx = 0;
8249 
8250 	stats_paddr = st->stats_paddr;
8251 	for (i = 0; i < BWI_TXSTATS_NDESC; ++i) {
8252 		bwi_setup_desc32(sc, st->stats_ring, BWI_TXSTATS_NDESC, i,
8253 				 stats_paddr, sizeof(struct bwi_txstats), 0);
8254 		stats_paddr += sizeof(struct bwi_txstats);
8255 	}
8256 	bus_dmamap_sync(sc->sc_dmat, st->stats_ring_dmap, 0,
8257 	    st->stats_ring_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
8258 
8259 	bwi_init_rxdesc_ring32(sc, st->stats_ctrl_base,
8260 	    st->stats_ring_paddr, 0, BWI_TXSTATS_NDESC);
8261 
8262 	return (0);
8263 }
8264 
8265 static void
8266 bwi_setup_rx_desc32(struct bwi_softc *sc, int buf_idx, bus_addr_t paddr,
8267     int buf_len)
8268 {
8269 	struct bwi_ring_data *rd = &sc->sc_rx_rdata;
8270 
8271 	KASSERT(buf_idx < BWI_RX_NDESC);
8272 	bwi_setup_desc32(sc, rd->rdata_desc, BWI_RX_NDESC, buf_idx,
8273 	    paddr, buf_len, 0);
8274 }
8275 
8276 static void
8277 bwi_setup_tx_desc32(struct bwi_softc *sc, struct bwi_ring_data *rd,
8278     int buf_idx, bus_addr_t paddr, int buf_len)
8279 {
8280 	KASSERT(buf_idx < BWI_TX_NDESC);
8281 	bwi_setup_desc32(sc, rd->rdata_desc, BWI_TX_NDESC, buf_idx,
8282 	    paddr, buf_len, 1);
8283 }
8284 static int
8285 bwi_init_tx_ring64(struct bwi_softc *sc, int ring_idx)
8286 {
8287 	/* TODO: 64 */
8288 	return (EOPNOTSUPP);
8289 }
8290 
8291 static int
8292 bwi_init_rx_ring64(struct bwi_softc *sc)
8293 {
8294 	/* TODO: 64 */
8295 	return (EOPNOTSUPP);
8296 }
8297 
8298 static int
8299 bwi_init_txstats64(struct bwi_softc *sc)
8300 {
8301 	/* TODO: 64 */
8302 	return (EOPNOTSUPP);
8303 }
8304 
8305 static void
8306 bwi_setup_rx_desc64(struct bwi_softc *sc, int buf_idx, bus_addr_t paddr,
8307     int buf_len)
8308 {
8309 	/* TODO: 64 */
8310 }
8311 
8312 static void
8313 bwi_setup_tx_desc64(struct bwi_softc *sc, struct bwi_ring_data *rd,
8314     int buf_idx, bus_addr_t paddr, int buf_len)
8315 {
8316 	/* TODO: 64 */
8317 }
8318 
8319 static int
8320 bwi_newbuf(struct bwi_softc *sc, int buf_idx, int init)
8321 {
8322 	struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata;
8323 	struct bwi_rxbuf *rxbuf = &rbd->rbd_buf[buf_idx];
8324 	struct bwi_rxbuf_hdr *hdr;
8325 	bus_dmamap_t map;
8326 	bus_addr_t paddr;
8327 	struct mbuf *m;
8328 	int error;
8329 
8330 	KASSERT(buf_idx < BWI_RX_NDESC);
8331 
8332 	MGETHDR(m, init ? M_WAITOK : M_DONTWAIT, MT_DATA);
8333 	if (m == NULL)
8334 		return (ENOBUFS);
8335 	MCLGET(m, init ? M_WAITOK : M_DONTWAIT);
8336 	if ((m->m_flags & M_EXT) == 0) {
8337 		error = ENOBUFS;
8338 
8339 		/*
8340 		 * If the NIC is up and running, we need to:
8341 		 * - Clear RX buffer's header.
8342 		 * - Restore RX descriptor settings.
8343 		 */
8344 		if (init)
8345 			return error;
8346 		else
8347 			goto back;
8348 	}
8349 	m->m_len = m->m_pkthdr.len = MCLBYTES;
8350 
8351 	/*
8352 	 * Try to load RX buf into temporary DMA map
8353 	 */
8354 	error = bus_dmamap_load_mbuf(sc->sc_dmat, rbd->rbd_tmp_dmap, m,
8355 	    init ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT);
8356 	if (error) {
8357 		m_freem(m);
8358 
8359 		/*
8360 		 * See the comment above
8361 		 */
8362 		if (init)
8363 			return error;
8364 		else
8365 			goto back;
8366 	}
8367 
8368 	if (!init)
8369 		bus_dmamap_unload(sc->sc_dmat, rxbuf->rb_dmap);
8370 	rxbuf->rb_mbuf = m;
8371 
8372 	/*
8373 	 * Swap RX buf's DMA map with the loaded temporary one
8374 	 */
8375 	map = rxbuf->rb_dmap;
8376 	rxbuf->rb_dmap = rbd->rbd_tmp_dmap;
8377 	rbd->rbd_tmp_dmap = map;
8378 	paddr = rxbuf->rb_dmap->dm_segs[0].ds_addr;
8379 	rxbuf->rb_paddr = paddr;
8380 
8381 back:
8382 	/*
8383 	 * Clear RX buf header
8384 	 */
8385 	hdr = mtod(rxbuf->rb_mbuf, struct bwi_rxbuf_hdr *);
8386 	memset(hdr, 0, sizeof(*hdr));
8387 	bus_dmamap_sync(sc->sc_dmat, rxbuf->rb_dmap, 0,
8388 	    rxbuf->rb_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
8389 
8390 	/*
8391 	 * Setup RX buf descriptor
8392 	 */
8393 	(sc->sc_setup_rxdesc)(sc, buf_idx, rxbuf->rb_paddr,
8394 	    rxbuf->rb_mbuf->m_len - sizeof(*hdr));
8395 	return error;
8396 }
8397 
8398 static void
8399 bwi_set_addr_filter(struct bwi_softc *sc, uint16_t addr_ofs,
8400     const uint8_t *addr)
8401 {
8402 	int i;
8403 
8404 	CSR_WRITE_2(sc, BWI_ADDR_FILTER_CTRL,
8405 	    BWI_ADDR_FILTER_CTRL_SET | addr_ofs);
8406 
8407 	for (i = 0; i < (IEEE80211_ADDR_LEN / 2); ++i) {
8408 		uint16_t addr_val;
8409 
8410 		addr_val = (uint16_t)addr[i * 2] |
8411 		    (((uint16_t)addr[(i * 2) + 1]) << 8);
8412 		CSR_WRITE_2(sc, BWI_ADDR_FILTER_DATA, addr_val);
8413 	}
8414 }
8415 
8416 static int
8417 bwi_set_chan(struct bwi_softc *sc, struct ieee80211_channel *c)
8418 {
8419 	struct ieee80211com *ic = &sc->sc_ic;
8420 	struct bwi_mac *mac;
8421 	/* uint16_t flags; */ /* [TRC: XXX See below.] */
8422 	uint chan;
8423 
8424 	KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
8425 	mac = (struct bwi_mac *)sc->sc_cur_regwin;
8426 
8427 	chan = ieee80211_chan2ieee(ic, c);
8428 
8429 	bwi_rf_set_chan(mac, chan, 0);
8430 
8431 	/* [TRC: XXX DragonFlyBSD sets up radio tap channel frequency
8432 	   and flags here.  OpenBSD does not, and appears to do so
8433 	   later (in bwi_rxeof and bwi_encap).] */
8434 
8435 	return (0);
8436 }
8437 
8438 static void
8439 bwi_next_scan(void *xsc)
8440 {
8441 	struct bwi_softc *sc = xsc;
8442 	struct ieee80211com *ic = &sc->sc_ic;
8443 	int s;
8444 
8445 	s = splnet();
8446 
8447 	if (ic->ic_state == IEEE80211_S_SCAN)
8448 		ieee80211_next_scan(ic);
8449 
8450 	splx(s);
8451 }
8452 
8453 static int
8454 bwi_rxeof(struct bwi_softc *sc, int end_idx)
8455 {
8456 	struct bwi_ring_data *rd = &sc->sc_rx_rdata;
8457 	struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata;
8458 	struct ieee80211com *ic = &sc->sc_ic;
8459 	struct ifnet *ifp = &sc->sc_if;
8460 	int s, idx, rx_data = 0;
8461 
8462 	idx = rbd->rbd_idx;
8463 	while (idx != end_idx) {
8464 		struct bwi_rxbuf *rb = &rbd->rbd_buf[idx];
8465 		struct bwi_rxbuf_hdr *hdr;
8466 		struct ieee80211_frame_min *wh;
8467 		struct ieee80211_node *ni;
8468 		struct mbuf *m;
8469 		const void *plcp;
8470 		uint16_t flags2;
8471 		int buflen, wh_ofs, hdr_extra, rssi, type, rate;
8472 
8473 		m = rb->rb_mbuf;
8474 		bus_dmamap_sync(sc->sc_dmat, rb->rb_dmap, 0,
8475 		    rb->rb_dmap->dm_mapsize, BUS_DMASYNC_POSTREAD);
8476 
8477 		if (bwi_newbuf(sc, idx, 0)) {
8478 			if_statinc(ifp, if_ierrors);
8479 			goto next;
8480 		}
8481 
8482 		hdr = mtod(m, struct bwi_rxbuf_hdr *);
8483 		flags2 = le16toh(hdr->rxh_flags2);
8484 
8485 		hdr_extra = 0;
8486 		if (flags2 & BWI_RXH_F2_TYPE2FRAME)
8487 			hdr_extra = 2;
8488 		wh_ofs = hdr_extra + 6; /* XXX magic number */
8489 
8490 		buflen = le16toh(hdr->rxh_buflen);
8491 		if (buflen < BWI_FRAME_MIN_LEN(wh_ofs)) {
8492 			aprint_error_dev(sc->sc_dev, "short frame %d,"
8493 			    " hdr_extra %d\n", buflen, hdr_extra);
8494 			if_statinc(ifp, if_ierrors);
8495 			m_freem(m);
8496 			goto next;
8497 		}
8498 
8499 		plcp = ((const uint8_t *)(hdr + 1) + hdr_extra);
8500 		rssi = bwi_calc_rssi(sc, hdr);
8501 
8502 		m_set_rcvif(m, ifp);
8503 		m->m_len = m->m_pkthdr.len = buflen + sizeof(*hdr);
8504 		m_adj(m, sizeof(*hdr) + wh_ofs);
8505 
8506 		if (htole16(hdr->rxh_flags1) & BWI_RXH_F1_OFDM)
8507 			rate = bwi_ofdm_plcp2rate(plcp);
8508 		else
8509 			rate = bwi_ds_plcp2rate(plcp);
8510 
8511 		s = splnet();
8512 
8513 		/* RX radio tap */
8514 		if (sc->sc_drvbpf != NULL) {
8515 			struct mbuf mb;
8516 			struct bwi_rx_radiotap_hdr *tap = &sc->sc_rxtap;
8517 
8518 			tap->wr_tsf = hdr->rxh_tsf;
8519 			tap->wr_flags = 0;
8520 			tap->wr_rate = rate;
8521 			tap->wr_chan_freq =
8522 			    htole16(ic->ic_bss->ni_chan->ic_freq);
8523 			tap->wr_chan_flags =
8524 			    htole16(ic->ic_bss->ni_chan->ic_flags);
8525 			tap->wr_antsignal = rssi;
8526 			tap->wr_antnoise = BWI_NOISE_FLOOR;
8527 
8528 			mb.m_data = (void *)tap;
8529 			mb.m_len = sc->sc_rxtap_len;
8530 			mb.m_next = m;
8531 			mb.m_nextpkt = NULL;
8532 			mb.m_owner = NULL;
8533 			mb.m_type = 0;
8534 			mb.m_flags = 0;
8535 			bpf_mtap3(sc->sc_drvbpf, &mb, BPF_D_IN);
8536 		}
8537 
8538 		m_adj(m, -IEEE80211_CRC_LEN);
8539 
8540 		wh = mtod(m, struct ieee80211_frame_min *);
8541 		ni = ieee80211_find_rxnode(ic, wh);
8542 		type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
8543 
8544 		ieee80211_input(ic, m, ni, hdr->rxh_rssi,
8545 		    le16toh(hdr->rxh_tsf));
8546 
8547 		ieee80211_free_node(ni);
8548 
8549 		if (type == IEEE80211_FC0_TYPE_DATA) {
8550 			rx_data = 1;
8551 			sc->sc_rx_rate = rate;
8552 		}
8553 
8554 		splx(s);
8555 next:
8556 		idx = (idx + 1) % BWI_RX_NDESC;
8557 	}
8558 
8559 	rbd->rbd_idx = idx;
8560 	bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0,
8561 	    rd->rdata_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
8562 
8563 	return (rx_data);
8564 }
8565 
8566 static int
8567 bwi_rxeof32(struct bwi_softc *sc)
8568 {
8569 	uint32_t val, rx_ctrl;
8570 	int end_idx, rx_data;
8571 
8572 	rx_ctrl = sc->sc_rx_rdata.rdata_txrx_ctrl;
8573 
8574 	val = CSR_READ_4(sc, rx_ctrl + BWI_RX32_STATUS);
8575 	end_idx = __SHIFTOUT(val, BWI_RX32_STATUS_INDEX_MASK) /
8576 	    sizeof(struct bwi_desc32);
8577 
8578 	rx_data = bwi_rxeof(sc, end_idx);
8579 
8580 	CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_INDEX,
8581 	    end_idx * sizeof(struct bwi_desc32));
8582 
8583 	return (rx_data);
8584 }
8585 
8586 static int
8587 bwi_rxeof64(struct bwi_softc *sc)
8588 {
8589 	/* TODO: 64 */
8590 	return (0);
8591 }
8592 
8593 static void
8594 bwi_reset_rx_ring32(struct bwi_softc *sc, uint32_t rx_ctrl)
8595 {
8596 	int i;
8597 
8598 	CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_CTRL, 0);
8599 
8600 #define NRETRY 10
8601 	for (i = 0; i < NRETRY; ++i) {
8602 		uint32_t status;
8603 
8604 		status = CSR_READ_4(sc, rx_ctrl + BWI_RX32_STATUS);
8605 		if (__SHIFTOUT(status, BWI_RX32_STATUS_STATE_MASK) ==
8606 		    BWI_RX32_STATUS_STATE_DISABLED)
8607 			break;
8608 
8609 		DELAY(1000);
8610 	}
8611 	if (i == NRETRY)
8612 		aprint_error_dev(sc->sc_dev, "reset rx ring timedout\n");
8613 #undef NRETRY
8614 
8615 	CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_RINGINFO, 0);
8616 }
8617 
8618 static void
8619 bwi_free_txstats32(struct bwi_softc *sc)
8620 {
8621 	bwi_reset_rx_ring32(sc, sc->sc_txstats->stats_ctrl_base);
8622 }
8623 
8624 static void
8625 bwi_free_rx_ring32(struct bwi_softc *sc)
8626 {
8627 	struct bwi_ring_data *rd = &sc->sc_rx_rdata;
8628 	struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata;
8629 	int i;
8630 
8631 	bwi_reset_rx_ring32(sc, rd->rdata_txrx_ctrl);
8632 
8633 	for (i = 0; i < BWI_RX_NDESC; ++i) {
8634 		struct bwi_rxbuf *rb = &rbd->rbd_buf[i];
8635 
8636 		if (rb->rb_mbuf != NULL) {
8637 			bus_dmamap_unload(sc->sc_dmat, rb->rb_dmap);
8638 			m_freem(rb->rb_mbuf);
8639 			rb->rb_mbuf = NULL;
8640 		}
8641 	}
8642 }
8643 
8644 static void
8645 bwi_free_tx_ring32(struct bwi_softc *sc, int ring_idx)
8646 {
8647 	struct bwi_ring_data *rd;
8648 	struct bwi_txbuf_data *tbd;
8649 	uint32_t state, val;
8650 	int i;
8651 
8652 	KASSERT(ring_idx < BWI_TX_NRING);
8653 	rd = &sc->sc_tx_rdata[ring_idx];
8654 	tbd = &sc->sc_tx_bdata[ring_idx];
8655 
8656 #define NRETRY 10
8657 	for (i = 0; i < NRETRY; ++i) {
8658 		val = CSR_READ_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_STATUS);
8659 		state = __SHIFTOUT(val, BWI_TX32_STATUS_STATE_MASK);
8660 		if (state == BWI_TX32_STATUS_STATE_DISABLED ||
8661 		    state == BWI_TX32_STATUS_STATE_IDLE ||
8662 		    state == BWI_TX32_STATUS_STATE_STOPPED)
8663 			break;
8664 
8665 		DELAY(1000);
8666 	}
8667 	if (i == NRETRY)
8668 		aprint_error_dev(sc->sc_dev,
8669 		    "wait for TX ring(%d) stable timed out\n", ring_idx);
8670 
8671 	CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_CTRL, 0);
8672 	for (i = 0; i < NRETRY; ++i) {
8673 		val = CSR_READ_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_STATUS);
8674 		state = __SHIFTOUT(val, BWI_TX32_STATUS_STATE_MASK);
8675 		if (state == BWI_TX32_STATUS_STATE_DISABLED)
8676 			break;
8677 
8678 		DELAY(1000);
8679 	}
8680 	if (i == NRETRY)
8681 		aprint_error_dev(sc->sc_dev, "reset TX ring (%d) timed out\n",
8682 		    ring_idx);
8683 #undef NRETRY
8684 
8685 	DELAY(1000);
8686 
8687 	CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_RINGINFO, 0);
8688 
8689 	for (i = 0; i < BWI_TX_NDESC; ++i) {
8690 		struct bwi_txbuf *tb = &tbd->tbd_buf[i];
8691 
8692 		if (tb->tb_mbuf != NULL) {
8693 			bus_dmamap_unload(sc->sc_dmat, tb->tb_dmap);
8694 			m_freem(tb->tb_mbuf);
8695 			tb->tb_mbuf = NULL;
8696 		}
8697 		if (tb->tb_ni != NULL) {
8698 			ieee80211_free_node(tb->tb_ni);
8699 			tb->tb_ni = NULL;
8700 		}
8701 	}
8702 }
8703 
8704 static void
8705 bwi_free_txstats64(struct bwi_softc *sc)
8706 {
8707 	/* TODO: 64 */
8708 }
8709 
8710 static void
8711 bwi_free_rx_ring64(struct bwi_softc *sc)
8712 {
8713 	/* TODO: 64 */
8714 }
8715 
8716 static void
8717 bwi_free_tx_ring64(struct bwi_softc *sc, int ring_idx)
8718 {
8719 	/* TODO: 64 */
8720 }
8721 
8722 /* XXX does not belong here */
8723 /* [TRC: Begin pilferage from OpenBSD.] */
8724 
8725 /*
8726  * Convert bit rate (in 0.5Mbps units) to PLCP signal (R4-R1) and vice versa.
8727  */
8728 uint8_t
8729 bwi_ieee80211_rate2plcp(u_int8_t rate, enum ieee80211_phymode mode)
8730 {
8731 	rate &= IEEE80211_RATE_VAL;
8732 
8733 	if (mode == IEEE80211_MODE_11B) {
8734 		/* IEEE Std 802.11b-1999 page 15, subclause 18.2.3.3 */
8735 		switch (rate) {
8736 		case 2:		return 10;
8737 		case 4:		return 20;
8738 		case 11:	return 55;
8739 		case 22:	return 110;
8740 		/* IEEE Std 802.11g-2003 page 19, subclause 19.3.2.1 */
8741 		case 44:	return 220;
8742 		}
8743 	} else if (mode == IEEE80211_MODE_11G || mode == IEEE80211_MODE_11A) {
8744 		/* IEEE Std 802.11a-1999 page 14, subclause 17.3.4.1 */
8745 		switch (rate) {
8746 		case 12:	return 0x0b;
8747 		case 18:	return 0x0f;
8748 		case 24:	return 0x0a;
8749 		case 36:	return 0x0e;
8750 		case 48:	return 0x09;
8751 		case 72:	return 0x0d;
8752 		case 96:	return 0x08;
8753 		case 108:	return 0x0c;
8754 		}
8755         } else
8756 		panic("Unexpected mode %u", mode);
8757 
8758 	return 0;
8759 }
8760 
8761 static uint8_t
8762 bwi_ieee80211_plcp2rate(uint8_t plcp, enum ieee80211_phymode mode)
8763 {
8764 	if (mode == IEEE80211_MODE_11B) {
8765 		/* IEEE Std 802.11g-2003 page 19, subclause 19.3.2.1 */
8766 		switch (plcp) {
8767 		case 10:	return 2;
8768 		case 20:	return 4;
8769 		case 55:	return 11;
8770 		case 110:	return 22;
8771 		/* IEEE Std 802.11g-2003 page 19, subclause 19.3.2.1 */
8772 		case 220:	return 44;
8773 		}
8774 	} else if (mode == IEEE80211_MODE_11G || mode == IEEE80211_MODE_11A) {
8775 		/* IEEE Std 802.11a-1999 page 14, subclause 17.3.4.1 */
8776 		switch (plcp) {
8777 		case 0x0b:	return 12;
8778 		case 0x0f:	return 18;
8779 		case 0x0a:	return 24;
8780 		case 0x0e:	return 36;
8781 		case 0x09:	return 48;
8782 		case 0x0d:	return 72;
8783 		case 0x08:	return 96;
8784 		case 0x0c:	return 108;
8785 		}
8786 	} else
8787 		panic("Unexpected mode %u", mode);
8788 
8789 	return 0;
8790 }
8791 /* [TRC: End pilferage from OpenBSD.] */
8792 
8793 static enum bwi_ieee80211_modtype
8794 bwi_ieee80211_rate2modtype(uint8_t rate)
8795 {
8796 	rate &= IEEE80211_RATE_VAL;
8797 
8798 	if (rate == 44)
8799 		return (IEEE80211_MODTYPE_PBCC);
8800 	else if (rate == 22 || rate < 12)
8801 		return (IEEE80211_MODTYPE_DS);
8802 	else
8803 		return (IEEE80211_MODTYPE_OFDM);
8804 }
8805 
8806 static uint8_t
8807 bwi_ofdm_plcp2rate(const void *plcp0)
8808 {
8809 	uint32_t plcp;
8810 	uint8_t plcp_rate;
8811 
8812 	/* plcp0 may not be 32-bit aligned. */
8813 	plcp = le32dec(plcp0);
8814 	plcp_rate = __SHIFTOUT(plcp, IEEE80211_OFDM_PLCP_RATE_MASK);
8815 
8816 	return (bwi_ieee80211_plcp2rate(plcp_rate, IEEE80211_MODE_11G));
8817 }
8818 
8819 static uint8_t
8820 bwi_ds_plcp2rate(const struct ieee80211_ds_plcp_hdr *hdr)
8821 {
8822 	return (bwi_ieee80211_plcp2rate(hdr->i_signal, IEEE80211_MODE_11B));
8823 }
8824 
8825 static void
8826 bwi_ofdm_plcp_header(uint32_t *plcp0, int pkt_len, uint8_t rate)
8827 {
8828 	uint32_t plcp;
8829 
8830 	plcp = __SHIFTIN(bwi_ieee80211_rate2plcp(rate, IEEE80211_MODE_11G),
8831 	    IEEE80211_OFDM_PLCP_RATE_MASK) |
8832 	    __SHIFTIN(pkt_len, IEEE80211_OFDM_PLCP_LEN_MASK);
8833 	*plcp0 = htole32(plcp);
8834 }
8835 
8836 static void
8837 bwi_ds_plcp_header(struct ieee80211_ds_plcp_hdr *plcp, int pkt_len,
8838     uint8_t rate)
8839 {
8840 	int len, service, pkt_bitlen;
8841 
8842 	pkt_bitlen = pkt_len * NBBY;
8843 	len = howmany(pkt_bitlen * 2, rate);
8844 
8845 	service = IEEE80211_DS_PLCP_SERVICE_LOCKED;
8846 	if (rate == (11 * 2)) {
8847 		int pkt_bitlen1;
8848 
8849 		/*
8850 		 * PLCP service field needs to be adjusted,
8851 		 * if TX rate is 11Mbytes/s
8852 		 */
8853 		pkt_bitlen1 = len * 11;
8854 		if (pkt_bitlen1 - pkt_bitlen >= NBBY)
8855 			service |= IEEE80211_DS_PLCP_SERVICE_LENEXT7;
8856 	}
8857 
8858 	plcp->i_signal = bwi_ieee80211_rate2plcp(rate, IEEE80211_MODE_11B);
8859 	plcp->i_service = service;
8860 	plcp->i_length = htole16(len);
8861 	/* NOTE: do NOT touch i_crc */
8862 }
8863 
8864 static void
8865 bwi_plcp_header(void *plcp, int pkt_len, uint8_t rate)
8866 {
8867 	enum bwi_ieee80211_modtype modtype;
8868 
8869 	/*
8870 	 * Assume caller has zeroed 'plcp'
8871 	 */
8872 
8873 	modtype = bwi_ieee80211_rate2modtype(rate);
8874 	if (modtype == IEEE80211_MODTYPE_OFDM)
8875 		bwi_ofdm_plcp_header(plcp, pkt_len, rate);
8876 	else if (modtype == IEEE80211_MODTYPE_DS)
8877 		bwi_ds_plcp_header(plcp, pkt_len, rate);
8878 	else
8879 		panic("unsupport modulation type %u\n", modtype);
8880 }
8881 
8882 static uint8_t
8883 bwi_ieee80211_ack_rate(struct ieee80211_node *ni, uint8_t rate)
8884 {
8885 	const struct ieee80211_rateset *rs = &ni->ni_rates;
8886 	uint8_t ack_rate = 0;
8887 	enum bwi_ieee80211_modtype modtype;
8888 	int i;
8889 
8890 	rate &= IEEE80211_RATE_VAL;
8891 
8892 	modtype = bwi_ieee80211_rate2modtype(rate);
8893 
8894 	for (i = 0; i < rs->rs_nrates; ++i) {
8895 		uint8_t rate1 = rs->rs_rates[i] & IEEE80211_RATE_VAL;
8896 
8897 		if (rate1 > rate) {
8898 			if (ack_rate != 0)
8899 				return (ack_rate);
8900 			else
8901 				break;
8902 		}
8903 
8904 		if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC) &&
8905 		    bwi_ieee80211_rate2modtype(rate1) == modtype)
8906 			ack_rate = rate1;
8907 	}
8908 
8909 	switch (rate) {
8910 	/* CCK */
8911 	case 2:
8912 	case 4:
8913 	case 11:
8914 	case 22:
8915 		ack_rate = rate;
8916 		break;
8917 	/* PBCC */
8918 	case 44:
8919 		ack_rate = 22;
8920 		break;
8921 
8922 	/* OFDM */
8923 	case 12:
8924 	case 18:
8925 		ack_rate = 12;
8926 		break;
8927 	case 24:
8928 	case 36:
8929 		ack_rate = 24;
8930 		break;
8931 	case 48:
8932 	case 72:
8933 	case 96:
8934 	case 108:
8935 		ack_rate = 48;
8936 		break;
8937 	default:
8938 		panic("unsupported rate %d\n", rate);
8939 	}
8940 	return (ack_rate);
8941 }
8942 
8943 /* [TRC: XXX does not belong here] */
8944 
8945 #define IEEE80211_OFDM_TXTIME(kbps, frmlen)	\
8946 	(IEEE80211_OFDM_PREAMBLE_TIME +		\
8947 	 IEEE80211_OFDM_SIGNAL_TIME +		\
8948 	(IEEE80211_OFDM_NSYMS((kbps), (frmlen)) * IEEE80211_OFDM_SYM_TIME))
8949 
8950 #define IEEE80211_OFDM_SYM_TIME			4
8951 #define IEEE80211_OFDM_PREAMBLE_TIME		16
8952 #define IEEE80211_OFDM_SIGNAL_EXT_TIME		6
8953 #define IEEE80211_OFDM_SIGNAL_TIME		4
8954 
8955 #define IEEE80211_OFDM_PLCP_SERVICE_NBITS	16
8956 #define IEEE80211_OFDM_TAIL_NBITS		6
8957 
8958 #define IEEE80211_OFDM_NBITS(frmlen)		\
8959 	(IEEE80211_OFDM_PLCP_SERVICE_NBITS +	\
8960 	 ((frmlen) * NBBY) +			\
8961 	 IEEE80211_OFDM_TAIL_NBITS)
8962 
8963 #define IEEE80211_OFDM_NBITS_PER_SYM(kbps)	\
8964 	(((kbps) * IEEE80211_OFDM_SYM_TIME) / 1000)
8965 
8966 #define IEEE80211_OFDM_NSYMS(kbps, frmlen)	\
8967 	howmany(IEEE80211_OFDM_NBITS((frmlen)),	\
8968 	IEEE80211_OFDM_NBITS_PER_SYM((kbps)))
8969 
8970 #define IEEE80211_CCK_TXTIME(kbps, frmlen)	\
8971 	(((IEEE80211_CCK_NBITS((frmlen)) * 1000) + (kbps) - 1) / (kbps))
8972 
8973 #define IEEE80211_CCK_PREAMBLE_LEN		144
8974 #define IEEE80211_CCK_PLCP_HDR_TIME		48
8975 #define IEEE80211_CCK_SHPREAMBLE_LEN		72
8976 #define IEEE80211_CCK_SHPLCP_HDR_TIME		24
8977 
8978 #define IEEE80211_CCK_NBITS(frmlen)		((frmlen) * NBBY)
8979 
8980 static uint16_t
8981 bwi_ieee80211_txtime(struct ieee80211com *ic, struct ieee80211_node *ni,
8982     uint len, uint8_t rs_rate, uint32_t flags)
8983 {
8984 	enum bwi_ieee80211_modtype modtype;
8985 	uint16_t txtime;
8986 	int rate;
8987 
8988 	rs_rate &= IEEE80211_RATE_VAL;
8989 
8990 	rate = rs_rate * 500;	/* ieee80211 rate -> kbps */
8991 
8992 	modtype = bwi_ieee80211_rate2modtype(rs_rate);
8993 	if (modtype == IEEE80211_MODTYPE_OFDM) {
8994 		/*
8995 		 * IEEE Std 802.11a-1999, page 37, equation (29)
8996 		 * IEEE Std 802.11g-2003, page 44, equation (42)
8997 		 */
8998 		txtime = IEEE80211_OFDM_TXTIME(rate, len);
8999 		if (ic->ic_curmode == IEEE80211_MODE_11G)
9000 			txtime += IEEE80211_OFDM_SIGNAL_EXT_TIME;
9001 	} else {
9002 		/*
9003 		 * IEEE Std 802.11b-1999, page 28, subclause 18.3.4
9004 		 * IEEE Std 802.11g-2003, page 45, equation (43)
9005 		 */
9006 		if (modtype == IEEE80211_MODTYPE_PBCC)
9007 			++len;
9008 		txtime = IEEE80211_CCK_TXTIME(rate, len);
9009 
9010 		/*
9011 		 * Short preamble is not applicable for DS 1Mbits/s
9012 		 */
9013 		if (rs_rate != 2 && (flags & IEEE80211_F_SHPREAMBLE)) {
9014 			txtime += IEEE80211_CCK_SHPREAMBLE_LEN +
9015 				  IEEE80211_CCK_SHPLCP_HDR_TIME;
9016 		} else {
9017 			txtime += IEEE80211_CCK_PREAMBLE_LEN +
9018 				  IEEE80211_CCK_PLCP_HDR_TIME;
9019 		}
9020 	}
9021 	return (txtime);
9022 }
9023 
9024 static int
9025 bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
9026     struct ieee80211_node **nip, int mgt_pkt)
9027 {
9028 	struct ieee80211com *ic = &sc->sc_ic;
9029 	struct ieee80211_node *ni = *nip;
9030 	struct bwi_ring_data *rd = &sc->sc_tx_rdata[BWI_TX_DATA_RING];
9031 	struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING];
9032 	struct bwi_txbuf *tb = &tbd->tbd_buf[idx];
9033 	struct bwi_mac *mac;
9034 	struct bwi_txbuf_hdr *hdr;
9035 	struct ieee80211_frame *wh;
9036 	uint8_t rate;		/* [TRC: XXX Use a fallback rate?] */
9037 	uint32_t mac_ctrl;
9038 	uint16_t phy_ctrl;
9039 	bus_addr_t paddr;
9040 	int pkt_len, error, mcast_pkt = 0;
9041 #if 0
9042 	const uint8_t *p;
9043 	int i;
9044 #endif
9045 
9046 	KASSERT(ni != NULL);
9047 	KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
9048 	mac = (struct bwi_mac *)sc->sc_cur_regwin;
9049 
9050 	wh = mtod(m, struct ieee80211_frame *);
9051 
9052 	/* Get 802.11 frame len before prepending TX header */
9053 	pkt_len = m->m_pkthdr.len + IEEE80211_CRC_LEN;
9054 
9055 	/*
9056 	 * Find TX rate
9057 	 */
9058 	memset(tb->tb_rate_idx, 0, sizeof(tb->tb_rate_idx));
9059 	if (!mgt_pkt) {
9060 		if (ic->ic_fixed_rate != -1) {
9061 			rate = ic->ic_sup_rates[ic->ic_curmode].
9062 			    rs_rates[ic->ic_fixed_rate];
9063 			/* [TRC: XXX Set fallback rate.] */
9064 		} else {
9065 			/* AMRR rate control */
9066 			/* [TRC: XXX amrr] */
9067 			/* rate = ni->ni_rates.rs_rates[ni->ni_txrate]; */
9068 			rate = (1 * 2);
9069 			/* [TRC: XXX Set fallback rate.] */
9070 		}
9071 	} else {
9072 		/* Fixed at 1Mbits/s for mgt frames */
9073 		/* [TRC: XXX Set fallback rate.] */
9074 		rate = (1 * 2);
9075 	}
9076 
9077 	rate &= IEEE80211_RATE_VAL;
9078 
9079 	if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
9080 		/* [TRC: XXX Set fallback rate.] */
9081 		rate = ic->ic_mcast_rate;
9082 		mcast_pkt = 1;
9083 	}
9084 
9085 	/* [TRC: XXX Check fallback rate.] */
9086 	if (rate == 0) {
9087 		aprint_error_dev(sc->sc_dev, "invalid rate %u", rate);
9088 		/* [TRC: In the margin of the following line,
9089 		   DragonFlyBSD writes `Force 1Mbits/s', whereas
9090 		   OpenBSD writes `Force 1Mbytes/s'.] */
9091 		rate = (1 * 2);
9092 		/* [TRC: XXX Set fallback rate.] */
9093 	}
9094 	sc->sc_tx_rate = rate;
9095 
9096 	/* TX radio tap */
9097 	if (sc->sc_drvbpf != NULL) {
9098 		struct mbuf mb;
9099 		struct bwi_tx_radiotap_hdr *tap = &sc->sc_txtap;
9100 
9101 		tap->wt_flags = 0;
9102 		tap->wt_rate = rate;
9103 		tap->wt_chan_freq =
9104 		    htole16(ic->ic_bss->ni_chan->ic_freq);
9105 		tap->wt_chan_flags =
9106 		    htole16(ic->ic_bss->ni_chan->ic_flags);
9107 
9108 		mb.m_data = (void *)tap;
9109 		mb.m_len = sc->sc_txtap_len;
9110 		mb.m_next = m;
9111 		mb.m_nextpkt = NULL;
9112 		mb.m_type = 0;
9113 		mb.m_flags = 0;
9114 		bpf_mtap3(sc->sc_drvbpf, &mb, BPF_D_OUT);
9115 	}
9116 
9117 	/*
9118 	 * Setup the embedded TX header
9119 	 */
9120 	M_PREPEND(m, sizeof(*hdr), M_DONTWAIT);
9121 	if (m == NULL) {
9122 		aprint_error_dev(sc->sc_dev, "prepend TX header failed\n");
9123 		return (ENOBUFS);
9124 	}
9125 	hdr = mtod(m, struct bwi_txbuf_hdr *);
9126 
9127 	memset(hdr, 0, sizeof(*hdr));
9128 
9129 	memcpy(hdr->txh_fc, wh->i_fc, sizeof(hdr->txh_fc));
9130 	memcpy(hdr->txh_addr1, wh->i_addr1, sizeof(hdr->txh_addr1));
9131 
9132 	if (!mcast_pkt) {
9133 		uint16_t dur;
9134 		uint8_t ack_rate;
9135 
9136 		/* [TRC: XXX Set fallback rate.] */
9137 		ack_rate = bwi_ieee80211_ack_rate(ni, rate);
9138 		dur = bwi_ieee80211_txtime(ic, ni,
9139 		    sizeof(struct ieee80211_frame_ack) + IEEE80211_CRC_LEN,
9140 		    ack_rate, ic->ic_flags & IEEE80211_F_SHPREAMBLE);
9141 
9142 		hdr->txh_fb_duration = htole16(dur);
9143 	}
9144 
9145 	hdr->txh_id = htole16(
9146 	    __SHIFTIN(BWI_TX_DATA_RING, BWI_TXH_ID_RING_MASK) |
9147 	    __SHIFTIN(idx, BWI_TXH_ID_IDX_MASK));
9148 
9149 	bwi_plcp_header(hdr->txh_plcp, pkt_len, rate);
9150 	/* [TRC: XXX Use fallback rate.] */
9151 	bwi_plcp_header(hdr->txh_fb_plcp, pkt_len, rate);
9152 
9153 	phy_ctrl = __SHIFTIN(mac->mac_rf.rf_ant_mode,
9154 	    BWI_TXH_PHY_C_ANTMODE_MASK);
9155 	if (bwi_ieee80211_rate2modtype(rate) == IEEE80211_MODTYPE_OFDM)
9156 		phy_ctrl |= BWI_TXH_PHY_C_OFDM;
9157 	else if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && rate != (2 * 1))
9158 		phy_ctrl |= BWI_TXH_PHY_C_SHPREAMBLE;
9159 
9160 	mac_ctrl = BWI_TXH_MAC_C_HWSEQ | BWI_TXH_MAC_C_FIRST_FRAG;
9161 	if (!IEEE80211_IS_MULTICAST(wh->i_addr1))
9162 		mac_ctrl |= BWI_TXH_MAC_C_ACK;
9163 	if (bwi_ieee80211_rate2modtype(rate) == IEEE80211_MODTYPE_OFDM)
9164 		mac_ctrl |= BWI_TXH_MAC_C_FB_OFDM;
9165 
9166 	hdr->txh_mac_ctrl = htole32(mac_ctrl);
9167 	hdr->txh_phy_ctrl = htole16(phy_ctrl);
9168 
9169 	/* Catch any further usage */
9170 	hdr = NULL;
9171 	wh = NULL;
9172 
9173 	/* DMA load */
9174 	error = bus_dmamap_load_mbuf(sc->sc_dmat, tb->tb_dmap, m,
9175 	    BUS_DMA_NOWAIT);
9176 	if (error && error != EFBIG) {
9177 		aprint_error_dev(sc->sc_dev, "can't load TX buffer (1) %d\n",
9178 		    error);
9179 		goto back;
9180 	}
9181 
9182 	if (error) {	/* error == EFBIG */
9183 		struct mbuf *m_new;
9184 
9185 		error = 0;
9186 
9187 		MGETHDR(m_new, M_DONTWAIT, MT_DATA);
9188 		if (m_new == NULL) {
9189 			error = ENOBUFS;
9190 			aprint_error_dev(sc->sc_dev,
9191 			    "can't defrag TX buffer (1)\n");
9192 			goto back;
9193 		}
9194 
9195 		m_copy_pkthdr(m_new, m);
9196 		if (m->m_pkthdr.len > MHLEN) {
9197 			MCLGET(m_new, M_DONTWAIT);
9198 			if (!(m_new->m_flags & M_EXT)) {
9199 				m_freem(m_new);
9200 				error = ENOBUFS;
9201 			}
9202 		}
9203 
9204 		if (error) {
9205 			aprint_error_dev(sc->sc_dev,
9206 			    "can't defrag TX buffer (2)\n");
9207 			goto back;
9208 		}
9209 
9210 		m_copydata(m, 0, m->m_pkthdr.len, mtod(m_new, void *));
9211 		m_freem(m);
9212 		m_new->m_len = m_new->m_pkthdr.len;
9213 		m = m_new;
9214 
9215 		error = bus_dmamap_load_mbuf(sc->sc_dmat, tb->tb_dmap, m,
9216 		    BUS_DMA_NOWAIT);
9217 		if (error) {
9218 			aprint_error_dev(sc->sc_dev,
9219 			    "can't load TX buffer (2) %d\n", error);
9220 			goto back;
9221 		}
9222 	}
9223 	error = 0;
9224 
9225 	bus_dmamap_sync(sc->sc_dmat, tb->tb_dmap, 0,
9226 	    tb->tb_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
9227 
9228 	if (mgt_pkt || mcast_pkt) {
9229 		/* Don't involve mcast/mgt packets into TX rate control */
9230 		ieee80211_free_node(ni);
9231 		*nip = ni = NULL;
9232 	}
9233 
9234 	tb->tb_mbuf = m;
9235 	tb->tb_ni = ni;
9236 
9237 #if 0
9238 	p = mtod(m, const uint8_t *);
9239 	for (i = 0; i < m->m_pkthdr.len; ++i) {
9240 		if (i % 8 == 0) {
9241 			if (i != 0)
9242 				aprint_debug("\n");
9243 			aprint_debug_dev(sc->sc_dev, "");
9244 		}
9245 		aprint_debug(" %02x", p[i]);
9246 	}
9247 	aprint_debug("\n");
9248 #endif
9249 
9250 	DPRINTF(sc, BWI_DBG_TX, "idx %d, pkt_len %d, buflen %d\n",
9251 	    idx, pkt_len, m->m_pkthdr.len);
9252 
9253 	/* Setup TX descriptor */
9254 	paddr = tb->tb_dmap->dm_segs[0].ds_addr;
9255 	(sc->sc_setup_txdesc)(sc, rd, idx, paddr, m->m_pkthdr.len);
9256 	bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0,
9257 	    rd->rdata_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
9258 
9259 	/* Kick start */
9260 	(sc->sc_start_tx)(sc, rd->rdata_txrx_ctrl, idx);
9261 
9262 back:
9263 	if (error)
9264 		m_freem(m);
9265 	return (error);
9266 }
9267 
9268 static void
9269 bwi_start_tx32(struct bwi_softc *sc, uint32_t tx_ctrl, int idx)
9270 {
9271 	idx = (idx + 1) % BWI_TX_NDESC;
9272 	CSR_WRITE_4(sc, tx_ctrl + BWI_TX32_INDEX,
9273 	    idx * sizeof(struct bwi_desc32));
9274 }
9275 
9276 static void
9277 bwi_start_tx64(struct bwi_softc *sc, uint32_t tx_ctrl, int idx)
9278 {
9279 	/* TODO: 64 */
9280 }
9281 
9282 static void
9283 bwi_txeof_status32(struct bwi_softc *sc)
9284 {
9285 	struct ifnet *ifp = &sc->sc_if;
9286 	uint32_t val, ctrl_base;
9287 	int end_idx, s;
9288 
9289 	s = splnet();
9290 
9291 	ctrl_base = sc->sc_txstats->stats_ctrl_base;
9292 
9293 	val = CSR_READ_4(sc, ctrl_base + BWI_RX32_STATUS);
9294 	end_idx = __SHIFTOUT(val, BWI_RX32_STATUS_INDEX_MASK) /
9295 	    sizeof(struct bwi_desc32);
9296 
9297 	bwi_txeof_status(sc, end_idx);
9298 
9299 	CSR_WRITE_4(sc, ctrl_base + BWI_RX32_INDEX,
9300 	    end_idx * sizeof(struct bwi_desc32));
9301 
9302 	if ((ifp->if_flags & IFF_OACTIVE) == 0)
9303 		ifp->if_start(ifp); /* [TRC: XXX Why not bwi_start?] */
9304 
9305 	splx(s);
9306 }
9307 
9308 static void
9309 bwi_txeof_status64(struct bwi_softc *sc)
9310 {
9311 	/* TODO: 64 */
9312 }
9313 
9314 static void
9315 _bwi_txeof(struct bwi_softc *sc, uint16_t tx_id)
9316 {
9317 	struct ifnet *ifp = &sc->sc_if;
9318 	struct bwi_txbuf_data *tbd;
9319 	struct bwi_txbuf *tb;
9320 	int ring_idx, buf_idx;
9321 
9322 	if (tx_id == 0) {
9323 		/* [TRC: XXX What is the severity of this message?] */
9324 		aprint_normal_dev(sc->sc_dev, "zero tx id\n");
9325 		return;
9326 	}
9327 
9328 	ring_idx = __SHIFTOUT(tx_id, BWI_TXH_ID_RING_MASK);
9329 	buf_idx = __SHIFTOUT(tx_id, BWI_TXH_ID_IDX_MASK);
9330 
9331 	KASSERT(ring_idx == BWI_TX_DATA_RING);
9332 	KASSERT(buf_idx < BWI_TX_NDESC);
9333 	tbd = &sc->sc_tx_bdata[ring_idx];
9334 	KASSERT(tbd->tbd_used > 0);
9335 	tbd->tbd_used--;
9336 
9337 	tb = &tbd->tbd_buf[buf_idx];
9338 
9339 	bus_dmamap_unload(sc->sc_dmat, tb->tb_dmap);
9340 	m_freem(tb->tb_mbuf);
9341 	tb->tb_mbuf = NULL;
9342 
9343 	if (tb->tb_ni != NULL) {
9344 		ieee80211_free_node(tb->tb_ni);
9345 		tb->tb_ni = NULL;
9346 	}
9347 
9348 	if (tbd->tbd_used == 0)
9349 		sc->sc_tx_timer = 0;
9350 
9351 	ifp->if_flags &= ~IFF_OACTIVE;
9352 }
9353 
9354 static void
9355 bwi_txeof_status(struct bwi_softc *sc, int end_idx)
9356 {
9357 	struct bwi_txstats_data *st = sc->sc_txstats;
9358 	int idx;
9359 
9360 	bus_dmamap_sync(sc->sc_dmat, st->stats_dmap, 0,
9361 	    st->stats_dmap->dm_mapsize, BUS_DMASYNC_POSTREAD);
9362 
9363 	idx = st->stats_idx;
9364 	while (idx != end_idx) {
9365 		/* [TRC: XXX Filter this out if it is not pending; see
9366 		   DragonFlyBSD's revision 1.5. */
9367 		_bwi_txeof(sc, le16toh(st->stats[idx].txs_id));
9368 		idx = (idx + 1) % BWI_TXSTATS_NDESC;
9369 	}
9370 	st->stats_idx = idx;
9371 }
9372 
9373 static void
9374 bwi_txeof(struct bwi_softc *sc)
9375 {
9376 	struct ifnet *ifp = &sc->sc_if;
9377 	int s;
9378 
9379 	s = splnet();
9380 
9381 	for (;;) {
9382 		uint32_t tx_status0;
9383 		uint16_t tx_id, tx_info;
9384 
9385 		tx_status0 = CSR_READ_4(sc, BWI_TXSTATUS_0);
9386 		if ((tx_status0 & BWI_TXSTATUS_0_MORE) == 0)
9387 			break;
9388 		(void)CSR_READ_4(sc, BWI_TXSTATUS_1);
9389 
9390 		tx_id = __SHIFTOUT(tx_status0, BWI_TXSTATUS_0_TXID_MASK);
9391 		tx_info = BWI_TXSTATUS_0_INFO(tx_status0);
9392 
9393 		if (tx_info & 0x30) /* XXX */
9394 			continue;
9395 
9396 		_bwi_txeof(sc, tx_id);
9397 
9398 		if_statinc(ifp, if_opackets);
9399 	}
9400 
9401 	if ((ifp->if_flags & IFF_OACTIVE) == 0)
9402 		ifp->if_start(ifp);
9403 
9404 	splx(s);
9405 }
9406 
9407 static int
9408 bwi_bbp_power_on(struct bwi_softc *sc, enum bwi_clock_mode clk_mode)
9409 {
9410 	bwi_power_on(sc, 1);
9411 
9412 	return (bwi_set_clock_mode(sc, clk_mode));
9413 }
9414 
9415 static void
9416 bwi_bbp_power_off(struct bwi_softc *sc)
9417 {
9418 	bwi_set_clock_mode(sc, BWI_CLOCK_MODE_SLOW);
9419 	bwi_power_off(sc, 1);
9420 }
9421 
9422 static int
9423 bwi_get_pwron_delay(struct bwi_softc *sc)
9424 {
9425 	struct bwi_regwin *com, *old;
9426 	struct bwi_clock_freq freq;
9427 	uint32_t val;
9428 	int error;
9429 
9430 	com = &sc->sc_com_regwin;
9431 	KASSERT(BWI_REGWIN_EXIST(com));
9432 
9433 	if ((sc->sc_cap & BWI_CAP_CLKMODE) == 0)
9434 		return (0);
9435 
9436 	error = bwi_regwin_switch(sc, com, &old);
9437 	if (error)
9438 		return (error);
9439 
9440 	bwi_get_clock_freq(sc, &freq);
9441 
9442 	val = CSR_READ_4(sc, BWI_PLL_ON_DELAY);
9443 	sc->sc_pwron_delay = howmany((val + 2) * 1000000, freq.clkfreq_min);
9444 	DPRINTF(sc, BWI_DBG_ATTACH, "power on delay %u\n", sc->sc_pwron_delay);
9445 
9446 	return (bwi_regwin_switch(sc, old, NULL));
9447 }
9448 
9449 static int
9450 bwi_bus_attach(struct bwi_softc *sc)
9451 {
9452 	struct bwi_regwin *bus, *old;
9453 	int error;
9454 
9455 	bus = &sc->sc_bus_regwin;
9456 
9457 	error = bwi_regwin_switch(sc, bus, &old);
9458 	if (error)
9459 		return (error);
9460 
9461 	if (!bwi_regwin_is_enabled(sc, bus))
9462 		bwi_regwin_enable(sc, bus, 0);
9463 
9464 	/* Disable interripts */
9465 	CSR_WRITE_4(sc, BWI_INTRVEC, 0);
9466 
9467 	return (bwi_regwin_switch(sc, old, NULL));
9468 }
9469 
9470 static const char *
9471 bwi_regwin_name(const struct bwi_regwin *rw)
9472 {
9473 	switch (rw->rw_type) {
9474 	case BWI_REGWIN_T_COM:
9475 		return ("COM");
9476 	case BWI_REGWIN_T_BUSPCI:
9477 		return ("PCI");
9478 	case BWI_REGWIN_T_MAC:
9479 		return ("MAC");
9480 	case BWI_REGWIN_T_BUSPCIE:
9481 		return ("PCIE");
9482 	}
9483 	panic("unknown regwin type 0x%04x\n", rw->rw_type);
9484 
9485 	return (NULL);
9486 }
9487 
9488 static uint32_t
9489 bwi_regwin_disable_bits(struct bwi_softc *sc)
9490 {
9491 	uint32_t busrev;
9492 
9493 	/* XXX cache this */
9494 	busrev = __SHIFTOUT(CSR_READ_4(sc, BWI_ID_LO), BWI_ID_LO_BUSREV_MASK);
9495 	DPRINTF(sc, BWI_DBG_ATTACH | BWI_DBG_INIT | BWI_DBG_MISC,
9496 	    "bus rev %u\n", busrev);
9497 
9498 	if (busrev == BWI_BUSREV_0)
9499 		return (BWI_STATE_LO_DISABLE1);
9500 	else if (busrev == BWI_BUSREV_1)
9501 		return (BWI_STATE_LO_DISABLE2);
9502 	else
9503 		return (BWI_STATE_LO_DISABLE1 | BWI_STATE_LO_DISABLE2);
9504 }
9505 
9506 static int
9507 bwi_regwin_is_enabled(struct bwi_softc *sc, struct bwi_regwin *rw)
9508 {
9509 	uint32_t val, disable_bits;
9510 
9511 	disable_bits = bwi_regwin_disable_bits(sc);
9512 	val = CSR_READ_4(sc, BWI_STATE_LO);
9513 
9514 	if ((val & (BWI_STATE_LO_CLOCK |
9515 		    BWI_STATE_LO_RESET |
9516 		    disable_bits)) == BWI_STATE_LO_CLOCK) {
9517 		DPRINTF(sc, BWI_DBG_ATTACH | BWI_DBG_INIT, "%s is enabled\n",
9518 		    bwi_regwin_name(rw));
9519 		return (1);
9520 	} else {
9521 		DPRINTF(sc, BWI_DBG_ATTACH | BWI_DBG_INIT, "%s is disabled\n",
9522 		    bwi_regwin_name(rw));
9523 		return (0);
9524 	}
9525 }
9526 
9527 static void
9528 bwi_regwin_disable(struct bwi_softc *sc, struct bwi_regwin *rw, uint32_t flags)
9529 {
9530 	uint32_t state_lo, disable_bits;
9531 	int i;
9532 
9533 	state_lo = CSR_READ_4(sc, BWI_STATE_LO);
9534 
9535 	/*
9536 	 * If current regwin is in 'reset' state, it was already disabled.
9537 	 */
9538 	if (state_lo & BWI_STATE_LO_RESET) {
9539 		DPRINTF(sc, BWI_DBG_ATTACH | BWI_DBG_INIT,
9540 		    "%s was already disabled\n", bwi_regwin_name(rw));
9541 		return;
9542 	}
9543 
9544 	disable_bits = bwi_regwin_disable_bits(sc);
9545 
9546 	/*
9547 	 * Disable normal clock
9548 	 */
9549 	state_lo = BWI_STATE_LO_CLOCK | disable_bits;
9550 	CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
9551 
9552 	/*
9553 	 * Wait until normal clock is disabled
9554 	 */
9555 #define NRETRY	1000
9556 	for (i = 0; i < NRETRY; ++i) {
9557 		state_lo = CSR_READ_4(sc, BWI_STATE_LO);
9558 		if (state_lo & disable_bits)
9559 			break;
9560 		DELAY(10);
9561 	}
9562 	if (i == NRETRY) {
9563 		aprint_error_dev(sc->sc_dev, "%s disable clock timeout\n",
9564 		    bwi_regwin_name(rw));
9565 	}
9566 
9567 	for (i = 0; i < NRETRY; ++i) {
9568 		uint32_t state_hi;
9569 
9570 		state_hi = CSR_READ_4(sc, BWI_STATE_HI);
9571 		if ((state_hi & BWI_STATE_HI_BUSY) == 0)
9572 			break;
9573 		DELAY(10);
9574 	}
9575 	if (i == NRETRY) {
9576 		aprint_error_dev(sc->sc_dev, "%s wait BUSY unset timeout\n",
9577 		    bwi_regwin_name(rw));
9578 	}
9579 #undef NRETRY
9580 
9581 	/*
9582 	 * Reset and disable regwin with gated clock
9583 	 */
9584 	state_lo = BWI_STATE_LO_RESET | disable_bits |
9585 	    BWI_STATE_LO_CLOCK | BWI_STATE_LO_GATED_CLOCK |
9586 	    __SHIFTIN(flags, BWI_STATE_LO_FLAGS_MASK);
9587 	CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
9588 
9589 	/* Flush pending bus write */
9590 	CSR_READ_4(sc, BWI_STATE_LO);
9591 	DELAY(1);
9592 
9593 	/* Reset and disable regwin */
9594 	state_lo = BWI_STATE_LO_RESET | disable_bits |
9595 		   __SHIFTIN(flags, BWI_STATE_LO_FLAGS_MASK);
9596 	CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
9597 
9598 	/* Flush pending bus write */
9599 	CSR_READ_4(sc, BWI_STATE_LO);
9600 	DELAY(1);
9601 }
9602 
9603 static void
9604 bwi_regwin_enable(struct bwi_softc *sc, struct bwi_regwin *rw, uint32_t flags)
9605 {
9606 	uint32_t state_lo, state_hi, imstate;
9607 
9608 	bwi_regwin_disable(sc, rw, flags);
9609 
9610 	/* Reset regwin with gated clock */
9611 	state_lo = BWI_STATE_LO_RESET |
9612 	    BWI_STATE_LO_CLOCK |
9613 	    BWI_STATE_LO_GATED_CLOCK |
9614 	    __SHIFTIN(flags, BWI_STATE_LO_FLAGS_MASK);
9615 	CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
9616 
9617 	/* Flush pending bus write */
9618 	CSR_READ_4(sc, BWI_STATE_LO);
9619 	DELAY(1);
9620 
9621 	state_hi = CSR_READ_4(sc, BWI_STATE_HI);
9622 	if (state_hi & BWI_STATE_HI_SERROR)
9623 		CSR_WRITE_4(sc, BWI_STATE_HI, 0);
9624 
9625 	imstate = CSR_READ_4(sc, BWI_IMSTATE);
9626 	if (imstate & (BWI_IMSTATE_INBAND_ERR | BWI_IMSTATE_TIMEOUT)) {
9627 		imstate &= ~(BWI_IMSTATE_INBAND_ERR | BWI_IMSTATE_TIMEOUT);
9628 		CSR_WRITE_4(sc, BWI_IMSTATE, imstate);
9629 	}
9630 
9631 	/* Enable regwin with gated clock */
9632 	state_lo = BWI_STATE_LO_CLOCK |
9633 	    BWI_STATE_LO_GATED_CLOCK |
9634 	    __SHIFTIN(flags, BWI_STATE_LO_FLAGS_MASK);
9635 	CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
9636 
9637 	/* Flush pending bus write */
9638 	CSR_READ_4(sc, BWI_STATE_LO);
9639 	DELAY(1);
9640 
9641 	/* Enable regwin with normal clock */
9642 	state_lo = BWI_STATE_LO_CLOCK |
9643 	    __SHIFTIN(flags, BWI_STATE_LO_FLAGS_MASK);
9644 	CSR_WRITE_4(sc, BWI_STATE_LO, state_lo);
9645 
9646 	/* Flush pending bus write */
9647 	CSR_READ_4(sc, BWI_STATE_LO);
9648 	DELAY(1);
9649 }
9650 
9651 static void
9652 bwi_set_bssid(struct bwi_softc *sc, const uint8_t *bssid)
9653 {
9654 	struct ieee80211com *ic = &sc->sc_ic;
9655 	struct bwi_mac *mac;
9656 	struct bwi_myaddr_bssid buf;
9657 	const uint8_t *p;
9658 	uint32_t val;
9659 	int n, i;
9660 
9661 	KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
9662 	mac = (struct bwi_mac *)sc->sc_cur_regwin;
9663 
9664 	bwi_set_addr_filter(sc, BWI_ADDR_FILTER_BSSID, bssid);
9665 
9666 	memcpy(buf.myaddr, ic->ic_myaddr, sizeof(buf.myaddr));
9667 	memcpy(buf.bssid, bssid, sizeof(buf.bssid));
9668 
9669 	n = sizeof(buf) / sizeof(val);
9670 	p = (const uint8_t *)&buf;
9671 	for (i = 0; i < n; ++i) {
9672 		int j;
9673 
9674 		val = 0;
9675 		for (j = 0; j < sizeof(val); ++j)
9676 			val |= ((uint32_t)(*p++)) << (j * 8);
9677 
9678 		TMPLT_WRITE_4(mac, 0x20 + (i * sizeof(val)), val);
9679 	}
9680 }
9681 
9682 static void
9683 bwi_updateslot(struct ifnet *ifp)
9684 {
9685 	struct bwi_softc *sc = ifp->if_softc;
9686 	struct ieee80211com *ic = &sc->sc_ic;
9687 	struct bwi_mac *mac;
9688 
9689 	if ((ifp->if_flags & IFF_RUNNING) == 0)
9690 		return;
9691 
9692 	DPRINTF(sc, BWI_DBG_80211, "%s\n", __func__);
9693 
9694 	KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
9695 	mac = (struct bwi_mac *)sc->sc_cur_regwin;
9696 
9697 	bwi_mac_updateslot(mac, (ic->ic_flags & IEEE80211_F_SHSLOT));
9698 }
9699 
9700 static void
9701 bwi_calibrate(void *xsc)
9702 {
9703 	struct bwi_softc *sc = xsc;
9704 	struct ieee80211com *ic = &sc->sc_ic;
9705 	int s;
9706 
9707 	s = splnet();
9708 
9709 	if (ic->ic_state == IEEE80211_S_RUN) {
9710 		struct bwi_mac *mac;
9711 
9712 		KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
9713 		mac = (struct bwi_mac *)sc->sc_cur_regwin;
9714 
9715 		if (ic->ic_opmode != IEEE80211_M_MONITOR) {
9716 			bwi_mac_calibrate_txpower(mac, sc->sc_txpwrcb_type);
9717 			sc->sc_txpwrcb_type = BWI_TXPWR_CALIB;
9718 		}
9719 
9720 		/* XXX 15 seconds */
9721 		callout_schedule(&sc->sc_calib_ch, hz * 15);
9722 	}
9723 
9724 	splx(s);
9725 }
9726 
9727 static int
9728 bwi_calc_rssi(struct bwi_softc *sc, const struct bwi_rxbuf_hdr *hdr)
9729 {
9730 	struct bwi_mac *mac;
9731 
9732 	KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC);
9733 	mac = (struct bwi_mac *)sc->sc_cur_regwin;
9734 
9735 	return (bwi_rf_calc_rssi(mac, hdr));
9736 }
9737 
9738 bool
9739 bwi_suspend(device_t dv, const pmf_qual_t *qual)
9740 {
9741 	struct bwi_softc *sc = device_private(dv);
9742 
9743 	bwi_power_off(sc, 0);
9744 	if (sc->sc_disable != NULL)
9745 		(sc->sc_disable)(sc, 1);
9746 
9747 	return true;
9748 }
9749 
9750 bool
9751 bwi_resume(device_t dv, const pmf_qual_t *qual)
9752 {
9753 	struct bwi_softc *sc = device_private(dv);
9754 
9755 	if (sc->sc_enable != NULL)
9756 		(sc->sc_enable)(sc, 1);
9757 	bwi_power_on(sc, 1);
9758 
9759 	return true;
9760 }
9761