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