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