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