| File: | dev/ic/bwi.c |
| Warning: | line 2449, column 2 Value stored to 'sc' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: bwi.c,v 1.134 2023/11/10 15:51:20 bluhm 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 NBPFILTER1 > 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_MASK0x0000000f 0x0000000f |
| 88 | #define IEEE80211_OFDM_PLCP_LEN_MASK0x0001ffe0 0x0001ffe0 |
| 89 | |
| 90 | /* |
| 91 | * Contention window (slots). |
| 92 | */ |
| 93 | #define IEEE80211_CW_MAX1023 1023 /* aCWmax */ |
| 94 | #define IEEE80211_CW_MIN_031 31 /* DS/CCK aCWmin, ERP aCWmin(0) */ |
| 95 | #define IEEE80211_CW_MIN_115 15 /* OFDM aCWmin, ERP aCWmin(1) */ |
| 96 | |
| 97 | #define __unused__attribute__((__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__attribute__((__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_CCKIEEE80211_MODTYPE_DS 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_WRSSI0x1000 0x1000 |
| 385 | #define BWI_PHYTBL_NOISE_SCALE0x1400 0x1400 |
| 386 | #define BWI_PHYTBL_NOISE0x1800 0x1800 |
| 387 | #define BWI_PHYTBL_ROTOR0x2000 0x2000 |
| 388 | #define BWI_PHYTBL_DELAY0x2400 0x2400 |
| 389 | #define BWI_PHYTBL_RSSI0x4000 0x4000 |
| 390 | #define BWI_PHYTBL_SIGMA_SQ0x5000 0x5000 |
| 391 | #define BWI_PHYTBL_WRSSI_REV10x5400 0x5400 |
| 392 | #define BWI_PHYTBL_FREQ0x5800 0x5800 |
| 393 | |
| 394 | static const uint16_t bwi_phy_freq_11g_rev1[] = |
| 395 | { BWI_PHY_FREQ_11G_REV10x0089, 0x02e9, 0x0409, 0x04e9, 0x05a9, 0x0669, 0x0709, 0x0789 , 0x0829, 0x08a9, 0x0929, 0x0989, 0x0a09, 0x0a69, 0x0ac9, 0x0b29 , 0x0ba9, 0x0be9, 0x0c49, 0x0ca9, 0x0d09, 0x0d69, 0x0da9, 0x0e09 , 0x0e69, 0x0ea9, 0x0f09, 0x0f49, 0x0fa9, 0x0fe9, 0x1029, 0x1089 , 0x10c9, 0x1109, 0x1169, 0x11a9, 0x11e9, 0x1229, 0x1289, 0x12c9 , 0x1309, 0x1349, 0x1389, 0x13c9, 0x1409, 0x1449, 0x14a9, 0x14e9 , 0x1529, 0x1569, 0x15a9, 0x15e9, 0x1629, 0x1669, 0x16a9, 0x16e8 , 0x1728, 0x1768, 0x17a8, 0x17e8, 0x1828, 0x1868, 0x18a8, 0x18e8 , 0x1928, 0x1968, 0x19a8, 0x19e8, 0x1a28, 0x1a68, 0x1aa8, 0x1ae8 , 0x1b28, 0x1b68, 0x1ba8, 0x1be8, 0x1c28, 0x1c68, 0x1ca8, 0x1ce8 , 0x1d28, 0x1d68, 0x1dc8, 0x1e08, 0x1e48, 0x1e88, 0x1ec8, 0x1f08 , 0x1f48, 0x1f88, 0x1fe8, 0x2028, 0x2068, 0x20a8, 0x2108, 0x2148 , 0x2188, 0x21c8, 0x2228, 0x2268, 0x22c8, 0x2308, 0x2348, 0x23a8 , 0x23e8, 0x2448, 0x24a8, 0x24e8, 0x2548, 0x25a8, 0x2608, 0x2668 , 0x26c8, 0x2728, 0x2787, 0x27e7, 0x2847, 0x28c7, 0x2947, 0x29a7 , 0x2a27, 0x2ac7, 0x2b47, 0x2be7, 0x2ca7, 0x2d67, 0x2e47, 0x2f67 , 0x3247, 0x3526, 0x3646, 0x3726, 0x3806, 0x38a6, 0x3946, 0x39e6 , 0x3a66, 0x3ae6, 0x3b66, 0x3bc6, 0x3c45, 0x3ca5, 0x3d05, 0x3d85 , 0x3de5, 0x3e45, 0x3ea5, 0x3ee5, 0x3f45, 0x3fa5, 0x4005, 0x4045 , 0x40a5, 0x40e5, 0x4145, 0x4185, 0x41e5, 0x4225, 0x4265, 0x42c5 , 0x4305, 0x4345, 0x43a5, 0x43e5, 0x4424, 0x4464, 0x44c4, 0x4504 , 0x4544, 0x4584, 0x45c4, 0x4604, 0x4644, 0x46a4, 0x46e4, 0x4724 , 0x4764, 0x47a4, 0x47e4, 0x4824, 0x4864, 0x48a4, 0x48e4, 0x4924 , 0x4964, 0x49a4, 0x49e4, 0x4a24, 0x4a64, 0x4aa4, 0x4ae4, 0x4b23 , 0x4b63, 0x4ba3, 0x4be3, 0x4c23, 0x4c63, 0x4ca3, 0x4ce3, 0x4d23 , 0x4d63, 0x4da3, 0x4de3, 0x4e23, 0x4e63, 0x4ea3, 0x4ee3, 0x4f23 , 0x4f63, 0x4fc3, 0x5003, 0x5043, 0x5083, 0x50c3, 0x5103, 0x5143 , 0x5183, 0x51e2, 0x5222, 0x5262, 0x52a2, 0x52e2, 0x5342, 0x5382 , 0x53c2, 0x5402, 0x5462, 0x54a2, 0x5502, 0x5542, 0x55a2, 0x55e2 , 0x5642, 0x5682, 0x56e2, 0x5722, 0x5782, 0x57e1, 0x5841, 0x58a1 , 0x5901, 0x5961, 0x59c1, 0x5a21, 0x5aa1, 0x5b01, 0x5b81, 0x5be1 , 0x5c61, 0x5d01, 0x5d80, 0x5e20, 0x5ee0, 0x5fa0, 0x6080, 0x61c0 }; |
| 396 | static const uint16_t bwi_phy_noise_11g_rev1[] = |
| 397 | { BWI_PHY_NOISE_11G_REV10x013c, 0x01f5, 0x031a, 0x0631, 0x0001, 0x0001, 0x0001, 0x0001 }; |
| 398 | static const uint16_t bwi_phy_noise_11g[] = |
| 399 | { BWI_PHY_NOISE_11G0x5484, 0x3c40, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; |
| 400 | static const uint32_t bwi_phy_rotor_11g_rev1[] = |
| 401 | { BWI_PHY_ROTOR_11G_REV10xfeb93ffd, 0xfec63ffd, 0xfed23ffd, 0xfedf3ffd, 0xfeec3ffe, 0xfef83ffe , 0xff053ffe, 0xff113ffe, 0xff1e3ffe, 0xff2a3fff, 0xff373fff, 0xff443fff, 0xff503fff, 0xff5d3fff, 0xff693fff, 0xff763fff, 0xff824000 , 0xff8f4000, 0xff9b4000, 0xffa84000, 0xffb54000, 0xffc14000, 0xffce4000, 0xffda4000, 0xffe74000, 0xfff34000, 0x00004000, 0x000d4000 , 0x00194000, 0x00264000, 0x00324000, 0x003f4000, 0x004b4000, 0x00584000, 0x00654000, 0x00714000, 0x007e4000, 0x008a3fff, 0x00973fff , 0x00a33fff, 0x00b03fff, 0x00bc3fff, 0x00c93fff, 0x00d63fff, 0x00e23ffe, 0x00ef3ffe, 0x00fb3ffe, 0x01083ffe, 0x01143ffe, 0x01213ffd , 0x012e3ffd, 0x013a3ffd, 0x01473ffd }; |
| 402 | static const uint16_t bwi_phy_noise_scale_11g_rev2[] = |
| 403 | { BWI_PHY_NOISE_SCALE_11G_REV20x6c77, 0x5162, 0x3b40, 0x3335, 0x2f2d, 0x2a2a, 0x2527, 0x1f21 , 0x1a1d, 0x1719, 0x1616, 0x1414, 0x1414, 0x1400, 0x1414, 0x1614 , 0x1716, 0x1a19, 0x1f1d, 0x2521, 0x2a27, 0x2f2a, 0x332d, 0x3b35 , 0x5140, 0x6c62, 0x0077 }; |
| 404 | static const uint16_t bwi_phy_noise_scale_11g_rev7[] = |
| 405 | { BWI_PHY_NOISE_SCALE_11G_REV70xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4 , 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4 , 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4 , 0xa4a4, 0xa4a4, 0x00a4 }; |
| 406 | static const uint16_t bwi_phy_noise_scale_11g[] = |
| 407 | { BWI_PHY_NOISE_SCALE_11G0xd8dd, 0xcbd4, 0xbcc0, 0xb6b7, 0xb2b0, 0xadad, 0xa7a9, 0x9fa1 , 0x969b, 0x9195, 0x8f8f, 0x8a8a, 0x8a8a, 0x8a00, 0x8a8a, 0x8f8a , 0x918f, 0x9695, 0x9f9b, 0xa7a1, 0xada9, 0xb2ad, 0xb6b0, 0xbcb7 , 0xcbc0, 0xd8d4, 0x00dd }; |
| 408 | static const uint16_t bwi_phy_sigma_sq_11g_rev2[] = |
| 409 | { BWI_PHY_SIGMA_SQ_11G_REV20x007a, 0x0075, 0x0071, 0x006c, 0x0067, 0x0063, 0x005e, 0x0059 , 0x0054, 0x0050, 0x004b, 0x0046, 0x0042, 0x003d, 0x003d, 0x003d , 0x003d, 0x003d, 0x003d, 0x003d, 0x003d, 0x003d, 0x003d, 0x003d , 0x003d, 0x003d, 0x0000, 0x003d, 0x003d, 0x003d, 0x003d, 0x003d , 0x003d, 0x003d, 0x003d, 0x003d, 0x003d, 0x003d, 0x003d, 0x003d , 0x0042, 0x0046, 0x004b, 0x0050, 0x0054, 0x0059, 0x005e, 0x0063 , 0x0067, 0x006c, 0x0071, 0x0075, 0x007a }; |
| 410 | static const uint16_t bwi_phy_sigma_sq_11g_rev7[] = |
| 411 | { BWI_PHY_SIGMA_SQ_11G_REV70x00de, 0x00dc, 0x00da, 0x00d8, 0x00d6, 0x00d4, 0x00d2, 0x00cf , 0x00cd, 0x00ca, 0x00c7, 0x00c4, 0x00c1, 0x00be, 0x00be, 0x00be , 0x00be, 0x00be, 0x00be, 0x00be, 0x00be, 0x00be, 0x00be, 0x00be , 0x00be, 0x00be, 0x0000, 0x00be, 0x00be, 0x00be, 0x00be, 0x00be , 0x00be, 0x00be, 0x00be, 0x00be, 0x00be, 0x00be, 0x00be, 0x00be , 0x00c1, 0x00c4, 0x00c7, 0x00ca, 0x00cd, 0x00cf, 0x00d2, 0x00d4 , 0x00d6, 0x00d8, 0x00da, 0x00dc, 0x00de }; |
| 412 | static const uint32_t bwi_phy_delay_11g_rev1[] = |
| 413 | { BWI_PHY_DELAY_11G_REV10xdb93cb87, 0xd666cf64, 0xd1fdd358, 0xcda6d826, 0xca38dd9f, 0xc729e2b4 , 0xc469e88e, 0xc26aee2b, 0xc0def46c, 0xc073fa62, 0xc01d00d5, 0xc0760743, 0xc1560d1e, 0xc2e51369, 0xc4ed18ff, 0xc7ac1ed7, 0xcb2823b2 , 0xcefa28d9, 0xd2f62d3f, 0xd7bb3197, 0xdce53568, 0xe1fe3875, 0xe7d13b35, 0xed663d35, 0xf39b3ec4, 0xf98e3fa7, 0x00004000, 0x06723fa7 , 0x0c653ec4, 0x129a3d35, 0x182f3b35, 0x1e023875, 0x231b3568, 0x28453197, 0x2d0a2d3f, 0x310628d9, 0x34d823b2, 0x38541ed7, 0x3b1318ff , 0x3d1b1369, 0x3eaa0d1e, 0x3f8a0743, 0x3fe300d5, 0x3f8dfa62, 0x3f22f46c, 0x3d96ee2b, 0x3b97e88e, 0x38d7e2b4, 0x35c8dd9f, 0x325ad826 , 0x2e03d358, 0x299acf64, 0x246dcb87 }; |
| 414 | |
| 415 | /* RF */ |
| 416 | #define RF_LO_WRITE(mac, lo)bwi_rf_lo_write((mac), (lo)) bwi_rf_lo_write((mac), (lo)) |
| 417 | |
| 418 | #define BWI_RF_2GHZ_CHAN(chan)(ieee80211_ieee2mhz((chan), 0x0080) - 2400) \ |
| 419 | (ieee80211_ieee2mhz((chan), IEEE80211_CHAN_2GHZ0x0080) - 2400) |
| 420 | |
| 421 | #define BWI_DEFAULT_IDLE_TSSI52 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 = bwi_rf_read(((mac)), (0xn)) (regs)->rf_##n = RF_READ((mac), 0x##n)bwi_rf_read(((mac)), (0x##n)) |
| 445 | #define RESTORE_RF_REG(mac, regs, n)bwi_rf_write(((mac)), (0xn), ((regs)->rf_n)) RF_WRITE((mac), 0x##n, (regs)->rf_##n)bwi_rf_write(((mac)), (0x##n), ((regs)->rf_##n)) |
| 446 | |
| 447 | #define SAVE_PHY_REG(mac, regs, n)(regs)->phy_n = bwi_phy_read(((mac)), (0xn)) (regs)->phy_##n = PHY_READ((mac), 0x##n)bwi_phy_read(((mac)), (0x##n)) |
| 448 | #define RESTORE_PHY_REG(mac, regs, n)bwi_phy_write(((mac)), (0xn), ((regs)->phy_n)) PHY_WRITE((mac), 0x##n, (regs)->phy_##n)bwi_phy_write(((mac)), (0x##n), ((regs)->phy_##n)) |
| 449 | |
| 450 | static const int8_t bwi_txpower_map_11b[BWI_TSSI_MAX64] = |
| 451 | { BWI_TXPOWER_MAP_11B0x4d, 0x4c, 0x4b, 0x4a, 0x4a, 0x49, 0x48, 0x47, 0x47, 0x46, 0x45 , 0x45, 0x44, 0x43, 0x42, 0x42, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x32, 0x31 , 0x30, 0x2f, 0x2d, 0x2c, 0x2b, 0x29, 0x28, 0x26, 0x25, 0x23, 0x21, 0x1f, 0x1d, 0x1a, 0x17, 0x14, 0x10, 0x0c, 0x06, 0x00, - 7, -7, -7, -7, -7, -7, -7, -7, -7, -7, -7, -7 }; |
| 452 | static const int8_t bwi_txpower_map_11g[BWI_TSSI_MAX64] = |
| 453 | { BWI_TXPOWER_MAP_11G77, 77, 77, 76, 76, 76, 75, 75, 74, 74, 73, 73, 73, 72, 72, 71 , 71, 70, 70, 69, 68, 68, 67, 67, 66, 65, 65, 64, 63, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 50, 49, 47, 45, 43, 40 , 37, 33, 28, 22, 14, 5, -7, -20, -20, -20, -20, -20, -20, -20 , -20, -20, -20 }; |
| 454 | |
| 455 | /* IF_BWI */ |
| 456 | |
| 457 | struct bwi_myaddr_bssid { |
| 458 | uint8_t myaddr[IEEE80211_ADDR_LEN6]; |
| 459 | uint8_t bssid[IEEE80211_ADDR_LEN6]; |
| 460 | } __packed__attribute__((__packed__)); |
| 461 | |
| 462 | #define IEEE80211_DS_PLCP_SERVICE_LOCKED0x04 0x04 |
| 463 | #define IEEE80211_DS_PLCL_SERVICE_PBCC0x08 0x08 |
| 464 | #define IEEE80211_DS_PLCP_SERVICE_LENEXT50x20 0x20 |
| 465 | #define IEEE80211_DS_PLCP_SERVICE_LENEXT60x40 0x40 |
| 466 | #define IEEE80211_DS_PLCP_SERVICE_LENEXT70x80 0x80 |
| 467 | |
| 468 | struct cfdriver bwi_cd = { |
| 469 | NULL((void *)0), "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_MAX3] = { |
| 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_MAX4]; |
| 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_MAX4] = |
| 533 | { BWI_VENDOR_LED_ACT_DEFAULT2, 5, 4, 0 }; |
| 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_LEN6]; |
| 566 | |
| 567 | |
| 568 | /* CODE */ |
| 569 | |
| 570 | int |
| 571 | bwi_intr(void *xsc) |
| 572 | { |
| 573 | struct bwi_softc *sc = xsc; |
| 574 | struct bwi_mac *mac; |
| 575 | struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if; |
| 576 | uint32_t intr_status; |
| 577 | uint32_t txrx_intr_status[BWI_TXRX_NRING6]; |
| 578 | int i, txrx_error, tx = 0, rx_data = -1; |
| 579 | |
| 580 | if ((ifp->if_flags & IFF_RUNNING0x40) == 0) |
| 581 | return (0); |
| 582 | |
| 583 | /* |
| 584 | * Get interrupt status |
| 585 | */ |
| 586 | intr_status = CSR_READ_4(sc, BWI_MAC_INTR_STATUS)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000128 )))); |
| 587 | if (intr_status == 0xffffffff) /* Not for us */ |
| 588 | return (0); |
| 589 | |
| 590 | intr_status &= CSR_READ_4(sc, BWI_MAC_INTR_MASK)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x0000012c )))); |
| 591 | if (intr_status == 0) /* Nothing is interesting */ |
| 592 | return (0); |
| 593 | |
| 594 | DPRINTF(2, "%s: intr status 0x%08x\n", |
| 595 | sc->sc_dev.dv_xname, intr_status); |
| 596 | |
| 597 | KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC)((sc->sc_cur_regwin->rw_type == 0x812) ? (void)0 : __assert ("diagnostic ", "/usr/src/sys/dev/ic/bwi.c", 597, "sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC" )); |
| 598 | mac = (struct bwi_mac *)sc->sc_cur_regwin; |
| 599 | |
| 600 | txrx_error = 0; |
| 601 | |
| 602 | for (i = 0; i < BWI_TXRX_NRING6; ++i) { |
| 603 | uint32_t mask; |
| 604 | |
| 605 | if (BWI_TXRX_IS_RX(i)((i) % 3 == 0)) |
| 606 | mask = BWI_TXRX_RX_INTRS(((1 << 15) | (1 << 14) | (1 << 12) | (1 << 11) | (1 << 10)) | (1 << 16)); |
| 607 | else |
| 608 | mask = BWI_TXRX_TX_INTRS((1 << 15) | (1 << 14) | (1 << 12) | (1 << 11) | (1 << 10)); |
| 609 | |
| 610 | txrx_intr_status[i] = |
| 611 | CSR_READ_4(sc, BWI_TXRX_INTR_STATUS(i))(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), (((0x20 + ((i) * 8)))))) & mask; |
| 612 | |
| 613 | if (txrx_intr_status[i] & BWI_TXRX_INTR_ERROR((1 << 15) | (1 << 14) | (1 << 12) | (1 << 11) | (1 << 10))) { |
| 614 | printf("%s: intr fatal TX/RX (%d) error 0x%08x\n", |
| 615 | sc->sc_dev.dv_xname, i, txrx_intr_status[i]); |
| 616 | txrx_error = 1; |
| 617 | } |
| 618 | } |
| 619 | |
| 620 | /* |
| 621 | * Acknowledge interrupt |
| 622 | */ |
| 623 | CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, intr_status)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000128 )), ((intr_status)))); |
| 624 | |
| 625 | for (i = 0; i < BWI_TXRX_NRING6; ++i) |
| 626 | CSR_WRITE_4(sc, BWI_TXRX_INTR_STATUS(i), txrx_intr_status[i])(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), (((0x20 + ((i) * 8)))), ((txrx_intr_status[i])))); |
| 627 | |
| 628 | /* Disable all interrupts */ |
| 629 | bwi_disable_intrs(sc, BWI_ALL_INTRS0xffffffff); |
| 630 | |
| 631 | if (intr_status & BWI_INTR_PHY_TXERR(1 << 11)) { |
| 632 | if (mac->mac_flags & BWI_MAC_F_PHYE_RESET0x80) { |
| 633 | printf("intr PHY TX error\n"); |
| 634 | /* XXX to netisr0? */ |
| 635 | bwi_init_statechg(sc, 0); |
| 636 | return (1); |
| 637 | } |
| 638 | } |
| 639 | |
| 640 | if (txrx_error) { |
| 641 | /* TODO: reset device */ |
| 642 | } |
| 643 | |
| 644 | if (intr_status & BWI_INTR_TBTT(1 << 2)) |
| 645 | bwi_mac_config_ps(mac); |
| 646 | |
| 647 | if (intr_status & BWI_INTR_EO_ATIM(1 << 5)) |
| 648 | printf("%s: EO_ATIM\n", sc->sc_dev.dv_xname); |
| 649 | |
| 650 | if (intr_status & BWI_INTR_PMQ(1 << 6)) { |
| 651 | for (;;) { |
| 652 | if ((CSR_READ_4(sc, BWI_MAC_PS_STATUS)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000140 )))) & 0x8) == 0) |
| 653 | break; |
| 654 | } |
| 655 | CSR_WRITE_2(sc, BWI_MAC_PS_STATUS, 0x2)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x00000140 )), ((0x2)))); |
| 656 | } |
| 657 | |
| 658 | if (intr_status & BWI_INTR_NOISE(1 << 18)) |
| 659 | printf("%s: intr noise\n", sc->sc_dev.dv_xname); |
| 660 | |
| 661 | if (txrx_intr_status[0] & BWI_TXRX_INTR_RX(1 << 16)) |
| 662 | rx_data = sc->sc_rxeof(sc); |
| 663 | |
| 664 | if (txrx_intr_status[3] & BWI_TXRX_INTR_RX(1 << 16)) { |
| 665 | sc->sc_txeof_status(sc); |
| 666 | tx = 1; |
| 667 | } |
| 668 | |
| 669 | if (intr_status & BWI_INTR_TX_DONE(1 << 29)) { |
| 670 | bwi_txeof(sc); |
| 671 | tx = 1; |
| 672 | } |
| 673 | |
| 674 | /* Re-enable interrupts */ |
| 675 | bwi_enable_intrs(sc, BWI_INIT_INTRS((1 << 0) | (1 << 1) | (1 << 2) | (1 << 5) | (1 << 6) | (1 << 9) | (1 << 11) | (1 << 15) | (1 << 16) | (1 << 18) | (1 << 28) | ( 1 << 29))); |
| 676 | |
| 677 | if (sc->sc_blink_led != NULL((void *)0) && sc->sc_led_blink) { |
| 678 | int evt = BWI_LED_EVENT_NONE-1; |
| 679 | |
| 680 | if (tx && rx_data > 0) { |
| 681 | if (sc->sc_rx_rate > sc->sc_tx_rate) |
| 682 | evt = BWI_LED_EVENT_RX2; |
| 683 | else |
| 684 | evt = BWI_LED_EVENT_TX1; |
| 685 | } else if (tx) { |
| 686 | evt = BWI_LED_EVENT_TX1; |
| 687 | } else if (rx_data > 0) { |
| 688 | evt = BWI_LED_EVENT_RX2; |
| 689 | } else if (rx_data == 0) { |
| 690 | evt = BWI_LED_EVENT_POLL0; |
| 691 | } |
| 692 | |
| 693 | if (evt != BWI_LED_EVENT_NONE-1) |
| 694 | bwi_led_event(sc, evt); |
| 695 | } |
| 696 | |
| 697 | return (1); |
| 698 | } |
| 699 | |
| 700 | int |
| 701 | bwi_attach(struct bwi_softc *sc) |
| 702 | { |
| 703 | struct ieee80211com *ic = &sc->sc_ic; |
| 704 | struct ifnet *ifp = &ic->ic_ific_ac.ac_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 | sc->sc_led_idle = (2350 * hz) / 1000; |
| 713 | sc->sc_led_blink = 1; |
| 714 | |
| 715 | /* AMRR rate control */ |
| 716 | sc->sc_amrr.amrr_min_success_threshold = 1; |
| 717 | sc->sc_amrr.amrr_max_success_threshold = 15; |
| 718 | timeout_set(&sc->sc_amrr_ch, bwi_amrr_timeout, sc); |
| 719 | |
| 720 | timeout_set(&sc->sc_scan_ch, bwi_next_scan, sc); |
| 721 | timeout_set(&sc->sc_calib_ch, bwi_calibrate, sc); |
| 722 | |
| 723 | bwi_power_on(sc, 1); |
| 724 | |
| 725 | error = bwi_bbp_attach(sc); |
| 726 | if (error) |
| 727 | goto fail; |
| 728 | |
| 729 | error = bwi_bbp_power_on(sc, BWI_CLOCK_MODE_FAST); |
| 730 | if (error) |
| 731 | goto fail; |
| 732 | |
| 733 | if (BWI_REGWIN_EXIST(&sc->sc_com_regwin)((&sc->sc_com_regwin)->rw_flags & 0x1)) { |
| 734 | error = bwi_set_clock_delay(sc); |
| 735 | if (error) |
| 736 | goto fail; |
| 737 | |
| 738 | error = bwi_set_clock_mode(sc, BWI_CLOCK_MODE_FAST); |
| 739 | if (error) |
| 740 | goto fail; |
| 741 | |
| 742 | error = bwi_get_pwron_delay(sc); |
| 743 | if (error) |
| 744 | goto fail; |
| 745 | } |
| 746 | |
| 747 | error = bwi_bus_attach(sc); |
| 748 | if (error) |
| 749 | goto fail; |
| 750 | |
| 751 | bwi_get_card_flags(sc); |
| 752 | |
| 753 | bwi_led_attach(sc); |
| 754 | |
| 755 | for (i = 0; i < sc->sc_nmac; ++i) { |
| 756 | struct bwi_regwin *old; |
| 757 | |
| 758 | mac = &sc->sc_mac[i]; |
| 759 | error = bwi_regwin_switch(sc, &mac->mac_regwin, &old); |
| 760 | if (error) |
| 761 | goto fail; |
| 762 | |
| 763 | error = bwi_mac_lateattach(mac); |
| 764 | if (error) |
| 765 | goto fail; |
| 766 | |
| 767 | error = bwi_regwin_switch(sc, old, NULL((void *)0)); |
| 768 | if (error) |
| 769 | goto fail; |
| 770 | } |
| 771 | |
| 772 | /* |
| 773 | * XXX First MAC is known to exist |
| 774 | * TODO2 |
| 775 | */ |
| 776 | mac = &sc->sc_mac[0]; |
| 777 | phy = &mac->mac_phy; |
| 778 | |
| 779 | bwi_bbp_power_off(sc); |
| 780 | |
| 781 | error = bwi_dma_alloc(sc); |
| 782 | if (error) |
| 783 | goto fail; |
| 784 | |
| 785 | /* setup interface */ |
| 786 | ifp->if_softc = sc; |
| 787 | ifp->if_ioctl = bwi_ioctl; |
| 788 | ifp->if_start = bwi_start; |
| 789 | ifp->if_watchdog = bwi_watchdog; |
| 790 | ifp->if_flags = IFF_SIMPLEX0x800 | IFF_BROADCAST0x2 | IFF_MULTICAST0x8000; |
| 791 | strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ16); |
| 792 | ifq_init_maxlen(&ifp->if_snd, IFQ_MAXLEN256); |
| 793 | |
| 794 | /* Get locale */ |
| 795 | sc->sc_locale = __SHIFTOUT(bwi_read_sprom(sc, BWI_SPROM_CARD_INFO),(((bwi_read_sprom(sc, 0x5c)) & ((0x0f << 8))) / ((( ((0x0f << 8)) - 1) & ((0x0f << 8))) ^ ((0x0f << 8)))) |
| 796 | BWI_SPROM_CARD_INFO_LOCALE)(((bwi_read_sprom(sc, 0x5c)) & ((0x0f << 8))) / ((( ((0x0f << 8)) - 1) & ((0x0f << 8))) ^ ((0x0f << 8)))); |
| 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 | if (phy->phy_mode == IEEE80211_MODE_11B || |
| 803 | phy->phy_mode == IEEE80211_MODE_11G) { |
| 804 | uint16_t chan_flags; |
| 805 | |
| 806 | ic->ic_sup_rates[IEEE80211_MODE_11B] = |
| 807 | ieee80211_std_rateset_11b; |
| 808 | |
| 809 | if (phy->phy_mode == IEEE80211_MODE_11B) { |
| 810 | chan_flags = IEEE80211_CHAN_B(0x0080 | 0x0020); |
| 811 | ic->ic_phytype = IEEE80211_T_DS; |
| 812 | } else { |
| 813 | chan_flags = IEEE80211_CHAN_CCK0x0020 | |
| 814 | IEEE80211_CHAN_OFDM0x0040 | |
| 815 | IEEE80211_CHAN_DYN0x0400 | |
| 816 | IEEE80211_CHAN_2GHZ0x0080; |
| 817 | ic->ic_phytype = IEEE80211_T_OFDM; |
| 818 | ic->ic_sup_rates[IEEE80211_MODE_11G] = |
| 819 | ieee80211_std_rateset_11g; |
| 820 | } |
| 821 | |
| 822 | /* XXX depend on locale */ |
| 823 | for (i = 1; i <= 14; ++i) { |
| 824 | ic->ic_channels[i].ic_freq = |
| 825 | ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ0x0080); |
| 826 | ic->ic_channels[i].ic_flags = chan_flags; |
| 827 | } |
| 828 | |
| 829 | bwi_get_eaddr(sc, BWI_SPROM_11BG_EADDR0x48, ic->ic_myaddr); |
| 830 | if (IEEE80211_IS_MULTICAST(ic->ic_myaddr)(*(ic->ic_myaddr) & 0x01)) { |
| 831 | bwi_get_eaddr(sc, BWI_SPROM_11A_EADDR0x54, ic->ic_myaddr); |
| 832 | if (IEEE80211_IS_MULTICAST(ic->ic_myaddr)(*(ic->ic_myaddr) & 0x01)) { |
| 833 | printf("%s: invalid MAC address: %s\n", |
| 834 | sc->sc_dev.dv_xname, |
| 835 | ether_sprintf(ic->ic_myaddr)); |
| 836 | } |
| 837 | } |
| 838 | } else if (phy->phy_mode == IEEE80211_MODE_11A) { |
| 839 | /* TODO: 11A */ |
| 840 | error = ENXIO6; |
| 841 | goto fail; |
| 842 | } else |
| 843 | panic("unknown phymode %d", phy->phy_mode); |
| 844 | |
| 845 | printf(", address %s\n", ether_sprintf(ic->ic_myaddr)); |
| 846 | |
| 847 | sc->sc_fw_version = BWI_FW_VERSION33; |
| 848 | sc->sc_dwell_time = 200; |
| 849 | |
| 850 | ic->ic_caps = IEEE80211_C_SHSLOT0x00000080 | |
| 851 | IEEE80211_C_SHPREAMBLE0x00000100 | |
| 852 | IEEE80211_C_WEP0x00000001 | |
| 853 | IEEE80211_C_RSN0x00001000 | |
| 854 | IEEE80211_C_MONITOR0x00000200; |
| 855 | ic->ic_state = IEEE80211_S_INIT; |
| 856 | ic->ic_opmode = IEEE80211_M_STA; |
| 857 | |
| 858 | ic->ic_updateslot = bwi_updateslot; |
| 859 | |
| 860 | if_attach(ifp); |
| 861 | ieee80211_ifattach(ifp); |
| 862 | |
| 863 | sc->sc_newstate = ic->ic_newstate; |
| 864 | ic->ic_newstate = bwi_newstate; |
| 865 | ic->ic_newassoc = bwi_newassoc; |
| 866 | ic->ic_node_alloc = bwi_node_alloc; |
| 867 | |
| 868 | ieee80211_media_init(ifp, bwi_media_change, ieee80211_media_status); |
| 869 | |
| 870 | if (error) { |
| 871 | ieee80211_ifdetach(ifp); |
| 872 | goto fail; |
| 873 | } |
| 874 | |
| 875 | #if NBPFILTER1 > 0 |
| 876 | bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO127, |
| 877 | sizeof(struct ieee80211_frame) + 64); |
| 878 | |
| 879 | sc->sc_rxtap_len = sizeof(sc->sc_rxtapu); |
| 880 | sc->sc_rxtapsc_rxtapu.th.wr_ihdr.it_len = htole16(sc->sc_rxtap_len)((__uint16_t)(sc->sc_rxtap_len)); |
| 881 | sc->sc_rxtapsc_rxtapu.th.wr_ihdr.it_present = htole32(BWI_RX_RADIOTAP_PRESENT)((__uint32_t)(((1 << IEEE80211_RADIOTAP_TSFT) | (1 << IEEE80211_RADIOTAP_FLAGS) | (1 << IEEE80211_RADIOTAP_RATE ) | (1 << IEEE80211_RADIOTAP_CHANNEL) | (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL ) | (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE)))); |
| 882 | |
| 883 | sc->sc_txtap_len = sizeof(sc->sc_txtapu); |
| 884 | sc->sc_txtapsc_txtapu.th.wt_ihdr.it_len = htole16(sc->sc_txtap_len)((__uint16_t)(sc->sc_txtap_len)); |
| 885 | sc->sc_txtapsc_txtapu.th.wt_ihdr.it_present = htole32(BWI_TX_RADIOTAP_PRESENT)((__uint32_t)(((1 << IEEE80211_RADIOTAP_FLAGS) | (1 << IEEE80211_RADIOTAP_RATE) | (1 << IEEE80211_RADIOTAP_CHANNEL )))); |
| 886 | #endif |
| 887 | |
| 888 | return (0); |
| 889 | fail: |
| 890 | return (error); |
| 891 | } |
| 892 | |
| 893 | int |
| 894 | bwi_detach(void *arg) |
| 895 | { |
| 896 | struct bwi_softc *sc = arg; |
| 897 | struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if; |
| 898 | int s, i; |
| 899 | |
| 900 | bwi_stop(sc, 1); |
| 901 | ieee80211_ifdetach(ifp); |
| 902 | if_detach(ifp); |
| 903 | |
| 904 | for (i = 0; i < sc->sc_nmac; ++i) |
| 905 | bwi_mac_detach(&sc->sc_mac[i]); |
| 906 | |
| 907 | s = splvm()splraise(0xa); |
| 908 | bwi_dma_free(sc); |
| 909 | splx(s)spllower(s); |
| 910 | bwi_dma_mbuf_destroy(sc, BWI_TX_NRING6, 1); |
| 911 | |
| 912 | return (0); |
| 913 | } |
| 914 | |
| 915 | /* MAC */ |
| 916 | |
| 917 | void |
| 918 | bwi_tmplt_write_4(struct bwi_mac *mac, uint32_t ofs, uint32_t val) |
| 919 | { |
| 920 | struct bwi_softc *sc = mac->mac_sc; |
| 921 | |
| 922 | if (mac->mac_flags & BWI_MAC_F_BSWAP0x1) |
| 923 | val = swap32(val)(__uint32_t)(__builtin_constant_p(val) ? (__uint32_t)(((__uint32_t )(val) & 0xff) << 24 | ((__uint32_t)(val) & 0xff00 ) << 8 | ((__uint32_t)(val) & 0xff0000) >> 8 | ((__uint32_t)(val) & 0xff000000) >> 24) : __swap32md (val)); |
| 924 | |
| 925 | CSR_WRITE_4(sc, BWI_MAC_TMPLT_CTRL, ofs)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000130 )), ((ofs)))); |
| 926 | CSR_WRITE_4(sc, BWI_MAC_TMPLT_DATA, val)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000134 )), ((val)))); |
| 927 | } |
| 928 | |
| 929 | void |
| 930 | bwi_hostflags_write(struct bwi_mac *mac, uint64_t flags) |
| 931 | { |
| 932 | uint64_t val; |
| 933 | |
| 934 | val = flags & 0xffff; |
| 935 | MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_LO, val)bwi_memobj_write_2((mac), (0x1), (0x5e), (val)); |
| 936 | |
| 937 | val = (flags >> 16) & 0xffff; |
| 938 | MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_MI, val)bwi_memobj_write_2((mac), (0x1), (0x60), (val)); |
| 939 | |
| 940 | /* HI has unclear meaning, so leave it as it is */ |
| 941 | } |
| 942 | |
| 943 | uint64_t |
| 944 | 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 | val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_MI)bwi_memobj_read_2((mac), (0x1), (0x60)); |
| 952 | flags |= val << 16; |
| 953 | |
| 954 | val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_HFLAGS_LO)bwi_memobj_read_2((mac), (0x1), (0x5e)); |
| 955 | flags |= val; |
| 956 | |
| 957 | return (flags); |
| 958 | } |
| 959 | |
| 960 | uint16_t |
| 961 | bwi_memobj_read_2(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0) |
| 962 | { |
| 963 | struct bwi_softc *sc = mac->mac_sc; |
| 964 | uint32_t data_reg; |
| 965 | int ofs; |
| 966 | |
| 967 | data_reg = BWI_MOBJ_DATA0x00000164; |
| 968 | ofs = ofs0 / 4; |
| 969 | |
| 970 | if (ofs0 % 4 != 0) |
| 971 | data_reg = BWI_MOBJ_DATA_UNALIGN0x0166; |
| 972 | |
| 973 | CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs))(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000160 )), ((((obj_id) << 16 | (ofs)))))); |
| 974 | return (CSR_READ_2(sc, data_reg)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((data_reg ))))); |
| 975 | } |
| 976 | |
| 977 | uint32_t |
| 978 | bwi_memobj_read_4(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0) |
| 979 | { |
| 980 | struct bwi_softc *sc = mac->mac_sc; |
| 981 | int ofs; |
| 982 | |
| 983 | ofs = ofs0 / 4; |
| 984 | if (ofs0 % 4 != 0) { |
| 985 | uint32_t ret; |
| 986 | |
| 987 | CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs))(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000160 )), ((((obj_id) << 16 | (ofs)))))); |
| 988 | ret = CSR_READ_2(sc, BWI_MOBJ_DATA_UNALIGN)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x0166 )))); |
| 989 | ret <<= 16; |
| 990 | |
| 991 | CSR_WRITE_4(sc, BWI_MOBJ_CTRL,(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000160 )), ((((obj_id) << 16 | (ofs + 1)))))) |
| 992 | BWI_MOBJ_CTRL_VAL(obj_id, ofs + 1))(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000160 )), ((((obj_id) << 16 | (ofs + 1)))))); |
| 993 | ret |= CSR_READ_2(sc, BWI_MOBJ_DATA)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x00000164 )))); |
| 994 | |
| 995 | return (ret); |
| 996 | } else { |
| 997 | CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs))(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000160 )), ((((obj_id) << 16 | (ofs)))))); |
| 998 | return (CSR_READ_4(sc, BWI_MOBJ_DATA)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000164 ))))); |
| 999 | } |
| 1000 | } |
| 1001 | |
| 1002 | void |
| 1003 | bwi_memobj_write_2(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0, |
| 1004 | uint16_t v) |
| 1005 | { |
| 1006 | struct bwi_softc *sc = mac->mac_sc; |
| 1007 | uint32_t data_reg; |
| 1008 | int ofs; |
| 1009 | |
| 1010 | data_reg = BWI_MOBJ_DATA0x00000164; |
| 1011 | ofs = ofs0 / 4; |
| 1012 | |
| 1013 | if (ofs0 % 4 != 0) |
| 1014 | data_reg = BWI_MOBJ_DATA_UNALIGN0x0166; |
| 1015 | |
| 1016 | CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs))(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000160 )), ((((obj_id) << 16 | (ofs)))))); |
| 1017 | CSR_WRITE_2(sc, data_reg, v)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((data_reg )), ((v)))); |
| 1018 | } |
| 1019 | |
| 1020 | void |
| 1021 | bwi_memobj_write_4(struct bwi_mac *mac, uint16_t obj_id, uint16_t ofs0, |
| 1022 | uint32_t v) |
| 1023 | { |
| 1024 | struct bwi_softc *sc = mac->mac_sc; |
| 1025 | int ofs; |
| 1026 | |
| 1027 | ofs = ofs0 / 4; |
| 1028 | if (ofs0 % 4 != 0) { |
| 1029 | CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs))(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000160 )), ((((obj_id) << 16 | (ofs)))))); |
| 1030 | CSR_WRITE_2(sc, BWI_MOBJ_DATA_UNALIGN, v >> 16)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x0166 )), ((v >> 16)))); |
| 1031 | CSR_WRITE_4(sc, BWI_MOBJ_CTRL,(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000160 )), ((((obj_id) << 16 | (ofs + 1)))))) |
| 1032 | BWI_MOBJ_CTRL_VAL(obj_id, ofs + 1))(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000160 )), ((((obj_id) << 16 | (ofs + 1)))))); |
| 1033 | CSR_WRITE_2(sc, BWI_MOBJ_DATA, v & 0xffff)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x00000164 )), ((v & 0xffff)))); |
| 1034 | } else { |
| 1035 | CSR_WRITE_4(sc, BWI_MOBJ_CTRL, BWI_MOBJ_CTRL_VAL(obj_id, ofs))(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000160 )), ((((obj_id) << 16 | (ofs)))))); |
| 1036 | CSR_WRITE_4(sc, BWI_MOBJ_DATA, v)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000164 )), ((v)))); |
| 1037 | } |
| 1038 | } |
| 1039 | |
| 1040 | int |
| 1041 | bwi_mac_lateattach(struct bwi_mac *mac) |
| 1042 | { |
| 1043 | int error; |
| 1044 | |
| 1045 | if (mac->mac_revmac_regwin.rw_rev >= 5) |
| 1046 | CSR_READ_4(mac->mac_sc, BWI_STATE_HI)(((mac->mac_sc)->sc_mem_bt)->read_4(((mac->mac_sc )->sc_mem_bh), ((0x00000f9c)))); /* dummy read */ |
| 1047 | |
| 1048 | bwi_mac_reset(mac, 1); |
| 1049 | |
| 1050 | error = bwi_phy_attach(mac); |
| 1051 | if (error) |
| 1052 | return (error); |
| 1053 | |
| 1054 | error = bwi_rf_attach(mac); |
| 1055 | if (error) |
| 1056 | return (error); |
| 1057 | |
| 1058 | /* Link 11B/G PHY, unlink 11A PHY */ |
| 1059 | if (mac->mac_phy.phy_mode == IEEE80211_MODE_11A) |
| 1060 | bwi_mac_reset(mac, 0); |
| 1061 | else |
| 1062 | bwi_mac_reset(mac, 1); |
| 1063 | |
| 1064 | error = bwi_mac_test(mac); |
| 1065 | if (error) |
| 1066 | return (error); |
| 1067 | |
| 1068 | error = bwi_mac_get_property(mac); |
| 1069 | if (error) |
| 1070 | return (error); |
| 1071 | |
| 1072 | error = bwi_rf_map_txpower(mac); |
| 1073 | if (error) |
| 1074 | return (error); |
| 1075 | |
| 1076 | bwi_rf_off(mac); |
| 1077 | CSR_WRITE_2(mac->mac_sc, BWI_BBP_ATTEN, BWI_BBP_ATTEN_MAGIC)(((mac->mac_sc)->sc_mem_bt)->write_2(((mac->mac_sc )->sc_mem_bh), ((0x03e6)), ((0x00f4)))); |
| 1078 | bwi_regwin_disable(mac->mac_sc, &mac->mac_regwin, 0); |
| 1079 | |
| 1080 | return (0); |
| 1081 | } |
| 1082 | |
| 1083 | int |
| 1084 | bwi_mac_init(struct bwi_mac *mac) |
| 1085 | { |
| 1086 | struct bwi_softc *sc = mac->mac_sc; |
| 1087 | int error, i; |
| 1088 | |
| 1089 | /* Clear MAC/PHY/RF states */ |
| 1090 | bwi_mac_setup_tpctl(mac); |
| 1091 | bwi_rf_clear_state(&mac->mac_rf); |
| 1092 | bwi_phy_clear_state(&mac->mac_phy); |
| 1093 | |
| 1094 | /* Enable MAC and linked it to PHY */ |
| 1095 | if (!bwi_regwin_is_enabled(sc, &mac->mac_regwin)) |
| 1096 | bwi_mac_reset(mac, 1); |
| 1097 | |
| 1098 | /* Initialize backplane */ |
| 1099 | error = bwi_bus_init(sc, mac); |
| 1100 | if (error) |
| 1101 | return (error); |
| 1102 | |
| 1103 | /* XXX work around for hardware bugs? */ |
| 1104 | if (sc->sc_bus_regwin.rw_rev <= 5 && |
| 1105 | sc->sc_bus_regwin.rw_type != BWI_REGWIN_T_BUSPCIE0x820) { |
| 1106 | CSR_SETBITS_4(sc, BWI_CONF_LO,((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x00000fa8))), ((((((sc))->sc_mem_bt)->read_4((((sc)) ->sc_mem_bh), (((0x00000fa8))))) | (((2) * ((((0x00000007) - 1) & (0x00000007)) ^ (0x00000007))) | ((3) * ((((0x00000070 ) - 1) & (0x00000070)) ^ (0x00000070)))))))) |
| 1107 | __SHIFTIN(BWI_CONF_LO_SERVTO, BWI_CONF_LO_SERVTO_MASK) |((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x00000fa8))), ((((((sc))->sc_mem_bt)->read_4((((sc)) ->sc_mem_bh), (((0x00000fa8))))) | (((2) * ((((0x00000007) - 1) & (0x00000007)) ^ (0x00000007))) | ((3) * ((((0x00000070 ) - 1) & (0x00000070)) ^ (0x00000070)))))))) |
| 1108 | __SHIFTIN(BWI_CONF_LO_REQTO, BWI_CONF_LO_REQTO_MASK))((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x00000fa8))), ((((((sc))->sc_mem_bt)->read_4((((sc)) ->sc_mem_bh), (((0x00000fa8))))) | (((2) * ((((0x00000007) - 1) & (0x00000007)) ^ (0x00000007))) | ((3) * ((((0x00000070 ) - 1) & (0x00000070)) ^ (0x00000070)))))))); |
| 1109 | } |
| 1110 | |
| 1111 | /* Calibrate PHY */ |
| 1112 | error = bwi_phy_calibrate(mac); |
| 1113 | if (error) { |
| 1114 | printf("%s: PHY calibrate failed\n", sc->sc_dev.dv_xname); |
| 1115 | return (error); |
| 1116 | } |
| 1117 | |
| 1118 | /* Prepare to initialize firmware */ |
| 1119 | CSR_WRITE_4(sc, BWI_MAC_STATUS,(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000120 )), (((1U << 2) | (1U << 10))))) |
| 1120 | BWI_MAC_STATUS_UCODE_JUMP0 |(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000120 )), (((1U << 2) | (1U << 10))))) |
| 1121 | BWI_MAC_STATUS_IHREN)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000120 )), (((1U << 2) | (1U << 10))))); |
| 1122 | |
| 1123 | /* |
| 1124 | * Load and initialize firmwares |
| 1125 | */ |
| 1126 | error = bwi_mac_fw_alloc(mac); |
| 1127 | if (error) |
| 1128 | return (error); |
| 1129 | |
| 1130 | error = bwi_mac_fw_load(mac); |
| 1131 | if (error) |
| 1132 | return (error); |
| 1133 | |
| 1134 | error = bwi_mac_gpio_init(mac); |
| 1135 | if (error) |
| 1136 | return (error); |
| 1137 | |
| 1138 | error = bwi_mac_fw_init(mac); |
| 1139 | if (error) |
| 1140 | return (error); |
| 1141 | |
| 1142 | /* |
| 1143 | * Turn on RF |
| 1144 | */ |
| 1145 | bwi_rf_on(mac); |
| 1146 | |
| 1147 | /* TODO: LED, hardware rf enabled is only related to LED setting */ |
| 1148 | |
| 1149 | /* |
| 1150 | * Initialize PHY |
| 1151 | */ |
| 1152 | CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03e6 )), ((0)))); |
| 1153 | bwi_phy_init(mac); |
| 1154 | |
| 1155 | /* TODO: interference mitigation */ |
| 1156 | |
| 1157 | /* |
| 1158 | * Setup antenna mode |
| 1159 | */ |
| 1160 | bwi_rf_set_ant_mode(mac, mac->mac_rf.rf_ant_mode); |
| 1161 | |
| 1162 | /* |
| 1163 | * Initialize operation mode (RX configuration) |
| 1164 | */ |
| 1165 | bwi_mac_opmode_init(mac); |
| 1166 | |
| 1167 | /* XXX what's these */ |
| 1168 | if (mac->mac_revmac_regwin.rw_rev < 3) { |
| 1169 | CSR_WRITE_2(sc, 0x60e, 0)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x60e )), ((0)))); |
| 1170 | CSR_WRITE_2(sc, 0x610, 0x8000)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x610 )), ((0x8000)))); |
| 1171 | CSR_WRITE_2(sc, 0x604, 0)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x604 )), ((0)))); |
| 1172 | CSR_WRITE_2(sc, 0x606, 0x200)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x606 )), ((0x200)))); |
| 1173 | } else { |
| 1174 | CSR_WRITE_4(sc, 0x188, 0x80000000)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x188 )), ((0x80000000)))); |
| 1175 | CSR_WRITE_4(sc, 0x18c, 0x2000000)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x18c )), ((0x2000000)))); |
| 1176 | } |
| 1177 | |
| 1178 | /* |
| 1179 | * Initialize TX/RX interrupts' mask |
| 1180 | */ |
| 1181 | CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_INTR_TIMER1)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000128 )), (((1 << 14))))); |
| 1182 | for (i = 0; i < BWI_TXRX_NRING6; ++i) { |
| 1183 | uint32_t intrs; |
| 1184 | |
| 1185 | if (BWI_TXRX_IS_RX(i)((i) % 3 == 0)) |
| 1186 | intrs = BWI_TXRX_RX_INTRS(((1 << 15) | (1 << 14) | (1 << 12) | (1 << 11) | (1 << 10)) | (1 << 16)); |
| 1187 | else |
| 1188 | intrs = BWI_TXRX_TX_INTRS((1 << 15) | (1 << 14) | (1 << 12) | (1 << 11) | (1 << 10)); |
| 1189 | CSR_WRITE_4(sc, BWI_TXRX_INTR_MASK(i), intrs)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), (((0x24 + ((i) * 8)))), ((intrs)))); |
| 1190 | } |
| 1191 | |
| 1192 | /* XXX what's this */ |
| 1193 | CSR_SETBITS_4(sc, BWI_STATE_LO, 0x100000)((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x00000f98))), ((((((sc))->sc_mem_bt)->read_4((((sc)) ->sc_mem_bh), (((0x00000f98))))) | (0x100000))))); |
| 1194 | |
| 1195 | /* Setup MAC power up delay */ |
| 1196 | CSR_WRITE_2(sc, BWI_MAC_POWERUP_DELAY, sc->sc_pwron_delay)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x06a8 )), ((sc->sc_pwron_delay)))); |
| 1197 | |
| 1198 | /* Set MAC regwin revision */ |
| 1199 | MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_MACREV, mac->mac_rev)bwi_memobj_write_2((mac), (0x1), (0x16), (mac->mac_regwin. rw_rev)); |
| 1200 | |
| 1201 | /* |
| 1202 | * Initialize host flags |
| 1203 | */ |
| 1204 | bwi_mac_hostflags_init(mac); |
| 1205 | |
| 1206 | /* |
| 1207 | * Initialize BSS parameters |
| 1208 | */ |
| 1209 | bwi_mac_bss_param_init(mac); |
| 1210 | |
| 1211 | /* |
| 1212 | * Initialize TX rings |
| 1213 | */ |
| 1214 | for (i = 0; i < BWI_TX_NRING6; ++i) { |
| 1215 | error = sc->sc_init_tx_ring(sc, i); |
| 1216 | if (error) { |
| 1217 | printf("%s: can't initialize %dth TX ring\n", |
| 1218 | sc->sc_dev.dv_xname, i); |
| 1219 | return (error); |
| 1220 | } |
| 1221 | } |
| 1222 | |
| 1223 | /* |
| 1224 | * Initialize RX ring |
| 1225 | */ |
| 1226 | error = sc->sc_init_rx_ring(sc); |
| 1227 | if (error) { |
| 1228 | printf("%s: can't initialize RX ring\n", sc->sc_dev.dv_xname); |
| 1229 | return (error); |
| 1230 | } |
| 1231 | |
| 1232 | /* |
| 1233 | * Initialize TX stats if the current MAC uses that |
| 1234 | */ |
| 1235 | if (mac->mac_flags & BWI_MAC_F_HAS_TXSTATS0x4) { |
| 1236 | error = sc->sc_init_txstats(sc); |
| 1237 | if (error) { |
| 1238 | printf("%s: can't initialize TX stats ring\n", |
| 1239 | sc->sc_dev.dv_xname); |
| 1240 | return (error); |
| 1241 | } |
| 1242 | } |
| 1243 | |
| 1244 | /* XXX what's these */ |
| 1245 | CSR_WRITE_2(sc, 0x612, 0x50)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x612 )), ((0x50)))); /* Force Pre-TBTT to 80? */ |
| 1246 | MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, 0x416, 0x50)bwi_memobj_write_2((mac), (0x1), (0x416), (0x50)); |
| 1247 | MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, 0x414, 0x1f4)bwi_memobj_write_2((mac), (0x1), (0x414), (0x1f4)); |
| 1248 | |
| 1249 | mac->mac_flags |= BWI_MAC_F_INITED0x8; |
| 1250 | |
| 1251 | return (0); |
| 1252 | } |
| 1253 | |
| 1254 | void |
| 1255 | bwi_mac_reset(struct bwi_mac *mac, int link_phy) |
| 1256 | { |
| 1257 | struct bwi_softc *sc = mac->mac_sc; |
| 1258 | uint32_t flags, state_lo, status; |
| 1259 | |
| 1260 | flags = BWI_STATE_LO_FLAG_PHYRST(1 << 1) | BWI_STATE_LO_FLAG_PHYCLKEN(1 << 0); |
| 1261 | if (link_phy) |
| 1262 | flags |= BWI_STATE_LO_FLAG_PHYLNK(1 << 11); |
| 1263 | bwi_regwin_enable(sc, &mac->mac_regwin, flags); |
| 1264 | DELAY(2000)(*delay_func)(2000); |
| 1265 | |
| 1266 | state_lo = CSR_READ_4(sc, BWI_STATE_LO)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000f98 )))); |
| 1267 | state_lo |= BWI_STATE_LO_GATED_CLOCK(1 << 17); |
| 1268 | state_lo &= ~__SHIFTIN(BWI_STATE_LO_FLAG_PHYRST,(((1 << 1)) * ((((0x3ffc0000) - 1) & (0x3ffc0000)) ^ (0x3ffc0000))) |
| 1269 | BWI_STATE_LO_FLAGS_MASK)(((1 << 1)) * ((((0x3ffc0000) - 1) & (0x3ffc0000)) ^ (0x3ffc0000))); |
| 1270 | CSR_WRITE_4(sc, BWI_STATE_LO, state_lo)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000f98 )), ((state_lo)))); |
| 1271 | /* Flush pending bus write */ |
| 1272 | CSR_READ_4(sc, BWI_STATE_LO)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000f98 )))); |
| 1273 | DELAY(1000)(*delay_func)(1000); |
| 1274 | |
| 1275 | state_lo &= ~BWI_STATE_LO_GATED_CLOCK(1 << 17); |
| 1276 | CSR_WRITE_4(sc, BWI_STATE_LO, state_lo)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000f98 )), ((state_lo)))); |
| 1277 | /* Flush pending bus write */ |
| 1278 | CSR_READ_4(sc, BWI_STATE_LO)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000f98 )))); |
| 1279 | DELAY(1000)(*delay_func)(1000); |
| 1280 | |
| 1281 | CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03e6 )), ((0)))); |
| 1282 | |
| 1283 | status = CSR_READ_4(sc, BWI_MAC_STATUS)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000120 )))); |
| 1284 | status |= BWI_MAC_STATUS_IHREN(1U << 10); |
| 1285 | if (link_phy) |
| 1286 | status |= BWI_MAC_STATUS_PHYLNK(1U << 31); |
| 1287 | else |
| 1288 | status &= ~BWI_MAC_STATUS_PHYLNK(1U << 31); |
| 1289 | CSR_WRITE_4(sc, BWI_MAC_STATUS, status)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000120 )), ((status)))); |
| 1290 | |
| 1291 | if (link_phy) { |
| 1292 | DPRINTF(1, "%s: PHY is linked\n", sc->sc_dev.dv_xname); |
| 1293 | mac->mac_phy.phy_flags |= BWI_PHY_F_LINKED0x2; |
| 1294 | } else { |
| 1295 | DPRINTF(1, "%s: PHY is unlinked\n", sc->sc_dev.dv_xname); |
| 1296 | mac->mac_phy.phy_flags &= ~BWI_PHY_F_LINKED0x2; |
| 1297 | } |
| 1298 | } |
| 1299 | |
| 1300 | void |
| 1301 | bwi_mac_set_tpctl_11bg(struct bwi_mac *mac, const struct bwi_tpctl *new_tpctl) |
| 1302 | { |
| 1303 | struct bwi_rf *rf = &mac->mac_rf; |
| 1304 | struct bwi_tpctl *tpctl = &mac->mac_tpctl; |
| 1305 | |
| 1306 | if (new_tpctl != NULL((void *)0)) { |
| 1307 | KASSERT(new_tpctl->bbp_atten <= BWI_BBP_ATTEN_MAX)((new_tpctl->bbp_atten <= 11) ? (void)0 : __assert("diagnostic " , "/usr/src/sys/dev/ic/bwi.c", 1307, "new_tpctl->bbp_atten <= BWI_BBP_ATTEN_MAX" )); |
| 1308 | KASSERT(new_tpctl->rf_atten <=((new_tpctl->rf_atten <= (rf->rf_rev < 6 ? 9 : 31 )) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c" , 1310, "new_tpctl->rf_atten <= (rf->rf_rev < 6 ? BWI_RF_ATTEN_MAX0 : BWI_RF_ATTEN_MAX1)" )) |
| 1309 | (rf->rf_rev < 6 ? BWI_RF_ATTEN_MAX0((new_tpctl->rf_atten <= (rf->rf_rev < 6 ? 9 : 31 )) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c" , 1310, "new_tpctl->rf_atten <= (rf->rf_rev < 6 ? BWI_RF_ATTEN_MAX0 : BWI_RF_ATTEN_MAX1)" )) |
| 1310 | : BWI_RF_ATTEN_MAX1))((new_tpctl->rf_atten <= (rf->rf_rev < 6 ? 9 : 31 )) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c" , 1310, "new_tpctl->rf_atten <= (rf->rf_rev < 6 ? BWI_RF_ATTEN_MAX0 : BWI_RF_ATTEN_MAX1)" )); |
| 1311 | KASSERT(new_tpctl->tp_ctrl1 <= BWI_TPCTL1_MAX)((new_tpctl->tp_ctrl1 <= 7) ? (void)0 : __assert("diagnostic " , "/usr/src/sys/dev/ic/bwi.c", 1311, "new_tpctl->tp_ctrl1 <= BWI_TPCTL1_MAX" )); |
| 1312 | |
| 1313 | tpctl->bbp_atten = new_tpctl->bbp_atten; |
| 1314 | tpctl->rf_atten = new_tpctl->rf_atten; |
| 1315 | tpctl->tp_ctrl1 = new_tpctl->tp_ctrl1; |
| 1316 | } |
| 1317 | |
| 1318 | /* Set BBP attenuation */ |
| 1319 | bwi_phy_set_bbp_atten(mac, tpctl->bbp_atten); |
| 1320 | |
| 1321 | /* Set RF attenuation */ |
| 1322 | RF_WRITE(mac, BWI_RFR_ATTEN, tpctl->rf_atten)bwi_rf_write((mac), (0x43), (tpctl->rf_atten)); |
| 1323 | MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_RF_ATTEN,bwi_memobj_write_2((mac), (0x1), (0x64), (tpctl->rf_atten) ) |
| 1324 | tpctl->rf_atten)bwi_memobj_write_2((mac), (0x1), (0x64), (tpctl->rf_atten) ); |
| 1325 | |
| 1326 | /* Set TX power */ |
| 1327 | if (rf->rf_type == BWI_RF_T_BCM20500x2050) { |
| 1328 | RF_FILT_SETBITS(mac, BWI_RFR_TXPWR, ~BWI_RFR_TXPWR1_MASK,bwi_rf_write(((mac)), ((0x52)), ((bwi_rf_read(((mac)), ((0x52 ))) & (~0x0070)) | (((tpctl->tp_ctrl1) * ((((0x0070) - 1) & (0x0070)) ^ (0x0070)))))) |
| 1329 | __SHIFTIN(tpctl->tp_ctrl1, BWI_RFR_TXPWR1_MASK))bwi_rf_write(((mac)), ((0x52)), ((bwi_rf_read(((mac)), ((0x52 ))) & (~0x0070)) | (((tpctl->tp_ctrl1) * ((((0x0070) - 1) & (0x0070)) ^ (0x0070)))))); |
| 1330 | } |
| 1331 | |
| 1332 | /* Adjust RF Local Oscillator */ |
| 1333 | if (mac->mac_phy.phy_mode == IEEE80211_MODE_11G) |
| 1334 | bwi_rf_lo_adjust(mac, tpctl); |
| 1335 | } |
| 1336 | |
| 1337 | int |
| 1338 | bwi_mac_test(struct bwi_mac *mac) |
| 1339 | { |
| 1340 | 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 | orig_val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0)bwi_memobj_read_4((mac), (0x1), (0)); |
| 1347 | |
| 1348 | /* Test 1 */ |
| 1349 | MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, TEST_VAL1)bwi_memobj_write_4((mac), (0x1), (0), (TEST_VAL1)); |
| 1350 | val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0)bwi_memobj_read_4((mac), (0x1), (0)); |
| 1351 | if (val != TEST_VAL1) { |
| 1352 | printf("%s: TEST1 failed\n", sc->sc_dev.dv_xname); |
| 1353 | return (ENXIO6); |
| 1354 | } |
| 1355 | |
| 1356 | /* Test 2 */ |
| 1357 | MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, TEST_VAL2)bwi_memobj_write_4((mac), (0x1), (0), (TEST_VAL2)); |
| 1358 | val = MOBJ_READ_4(mac, BWI_COMM_MOBJ, 0)bwi_memobj_read_4((mac), (0x1), (0)); |
| 1359 | if (val != TEST_VAL2) { |
| 1360 | printf("%s: TEST2 failed\n", sc->sc_dev.dv_xname); |
| 1361 | return (ENXIO6); |
| 1362 | } |
| 1363 | |
| 1364 | /* Restore to the original value */ |
| 1365 | MOBJ_WRITE_4(mac, BWI_COMM_MOBJ, 0, orig_val)bwi_memobj_write_4((mac), (0x1), (0), (orig_val)); |
| 1366 | |
| 1367 | val = CSR_READ_4(sc, BWI_MAC_STATUS)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000120 )))); |
| 1368 | if ((val & ~BWI_MAC_STATUS_PHYLNK(1U << 31)) != BWI_MAC_STATUS_IHREN(1U << 10)) { |
| 1369 | printf("%s: %s failed, MAC status 0x%08x\n", |
| 1370 | sc->sc_dev.dv_xname, __func__, val); |
| 1371 | return (ENXIO6); |
| 1372 | } |
| 1373 | |
| 1374 | val = CSR_READ_4(sc, BWI_MAC_INTR_STATUS)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000128 )))); |
| 1375 | if (val != 0) { |
| 1376 | printf("%s: %s failed, intr status %08x\n", |
| 1377 | sc->sc_dev.dv_xname, __func__, val); |
| 1378 | return (ENXIO6); |
| 1379 | } |
| 1380 | #undef TEST_VAL2 |
| 1381 | #undef TEST_VAL1 |
| 1382 | |
| 1383 | return (0); |
| 1384 | } |
| 1385 | |
| 1386 | void |
| 1387 | bwi_mac_setup_tpctl(struct bwi_mac *mac) |
| 1388 | { |
| 1389 | struct bwi_softc *sc = mac->mac_sc; |
| 1390 | struct bwi_rf *rf = &mac->mac_rf; |
| 1391 | struct bwi_phy *phy = &mac->mac_phy; |
| 1392 | struct bwi_tpctl *tpctl = &mac->mac_tpctl; |
| 1393 | |
| 1394 | /* Calc BBP attenuation */ |
| 1395 | if (rf->rf_type == BWI_RF_T_BCM20500x2050 && rf->rf_rev < 6) |
| 1396 | tpctl->bbp_atten = 0; |
| 1397 | else |
| 1398 | tpctl->bbp_atten = 2; |
| 1399 | |
| 1400 | /* Calc TX power CTRL1?? */ |
| 1401 | tpctl->tp_ctrl1 = 0; |
| 1402 | if (rf->rf_type == BWI_RF_T_BCM20500x2050) { |
| 1403 | if (rf->rf_rev == 1) |
| 1404 | tpctl->tp_ctrl1 = 3; |
| 1405 | else if (rf->rf_rev < 6) |
| 1406 | tpctl->tp_ctrl1 = 2; |
| 1407 | else if (rf->rf_rev == 8) |
| 1408 | tpctl->tp_ctrl1 = 1; |
| 1409 | } |
| 1410 | |
| 1411 | /* Empty TX power CTRL2?? */ |
| 1412 | tpctl->tp_ctrl2 = 0xffff; |
| 1413 | |
| 1414 | /* |
| 1415 | * Calc RF attenuation |
| 1416 | */ |
| 1417 | if (phy->phy_mode == IEEE80211_MODE_11A) { |
| 1418 | tpctl->rf_atten = 0x60; |
| 1419 | goto back; |
| 1420 | } |
| 1421 | |
| 1422 | if (BWI_IS_BRCM_BCM4309G(sc)((sc)->sc_pci_subvid == 0x14e4 && (sc)->sc_pci_subdid == 0x421) && sc->sc_pci_revid < 0x51) { |
| 1423 | tpctl->rf_atten = sc->sc_pci_revid < 0x43 ? 2 : 3; |
| 1424 | goto back; |
| 1425 | } |
| 1426 | |
| 1427 | tpctl->rf_atten = 5; |
| 1428 | |
| 1429 | if (rf->rf_type != BWI_RF_T_BCM20500x2050) { |
| 1430 | if (rf->rf_type == BWI_RF_T_BCM20530x2053 && rf->rf_rev == 1) |
| 1431 | 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 | switch (rf->rf_rev) { |
| 1442 | case 1: |
| 1443 | if (phy->phy_mode == IEEE80211_MODE_11G) { |
| 1444 | if (BWI_IS_BRCM_BCM4309G(sc)((sc)->sc_pci_subvid == 0x14e4 && (sc)->sc_pci_subdid == 0x421) || BWI_IS_BRCM_BU4306(sc)((sc)->sc_pci_subvid == 0x14e4 && (sc)->sc_pci_subdid == 0x416)) |
| 1445 | tpctl->rf_atten = 3; |
| 1446 | else |
| 1447 | tpctl->rf_atten = 1; |
| 1448 | } else { |
| 1449 | if (BWI_IS_BRCM_BCM4309G(sc)((sc)->sc_pci_subvid == 0x14e4 && (sc)->sc_pci_subdid == 0x421)) |
| 1450 | tpctl->rf_atten = 7; |
| 1451 | else |
| 1452 | tpctl->rf_atten = 6; |
| 1453 | } |
| 1454 | break; |
| 1455 | case 2: |
| 1456 | if (phy->phy_mode == IEEE80211_MODE_11G) { |
| 1457 | /* |
| 1458 | * NOTE: Order of following conditions is critical |
| 1459 | */ |
| 1460 | if (BWI_IS_BRCM_BCM4309G(sc)((sc)->sc_pci_subvid == 0x14e4 && (sc)->sc_pci_subdid == 0x421)) |
| 1461 | tpctl->rf_atten = 3; |
| 1462 | else if (BWI_IS_BRCM_BU4306(sc)((sc)->sc_pci_subvid == 0x14e4 && (sc)->sc_pci_subdid == 0x416)) |
| 1463 | tpctl->rf_atten = 5; |
| 1464 | else if (sc->sc_bbp_id == BWI_BBPID_BCM43200x4320) |
| 1465 | tpctl->rf_atten = 4; |
| 1466 | else |
| 1467 | tpctl->rf_atten = 3; |
| 1468 | } else { |
| 1469 | tpctl->rf_atten = 6; |
| 1470 | } |
| 1471 | break; |
| 1472 | case 4: |
| 1473 | case 5: |
| 1474 | tpctl->rf_atten = 1; |
| 1475 | break; |
| 1476 | case 8: |
| 1477 | tpctl->rf_atten = 0x1a; |
| 1478 | 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 | } |
| 1485 | |
| 1486 | void |
| 1487 | bwi_mac_dummy_xmit(struct bwi_mac *mac) |
| 1488 | { |
| 1489 | #define PACKET_LEN 5 |
| 1490 | struct bwi_softc *sc = mac->mac_sc; |
| 1491 | 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 | if (mac->mac_phy.phy_mode == IEEE80211_MODE_11A) { |
| 1502 | wait_max = 30; |
| 1503 | packet = packet_11a; |
| 1504 | val_50c = 1; |
| 1505 | } else { |
| 1506 | wait_max = 250; |
| 1507 | packet = packet_11bg; |
| 1508 | val_50c = 0; |
| 1509 | } |
| 1510 | |
| 1511 | for (i = 0; i < PACKET_LEN; ++i) |
| 1512 | TMPLT_WRITE_4(mac, i * 4, packet[i])bwi_tmplt_write_4((mac), (i * 4), (packet[i])); |
| 1513 | |
| 1514 | CSR_READ_4(sc, BWI_MAC_STATUS)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000120 )))); /* dummy read */ |
| 1515 | |
| 1516 | CSR_WRITE_2(sc, 0x568, 0)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x568 )), ((0)))); |
| 1517 | CSR_WRITE_2(sc, 0x7c0, 0)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x7c0 )), ((0)))); |
| 1518 | CSR_WRITE_2(sc, 0x50c, val_50c)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x50c )), ((val_50c)))); |
| 1519 | CSR_WRITE_2(sc, 0x508, 0)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x508 )), ((0)))); |
| 1520 | CSR_WRITE_2(sc, 0x50a, 0)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x50a )), ((0)))); |
| 1521 | CSR_WRITE_2(sc, 0x54c, 0)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x54c )), ((0)))); |
| 1522 | CSR_WRITE_2(sc, 0x56a, 0x14)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x56a )), ((0x14)))); |
| 1523 | CSR_WRITE_2(sc, 0x568, 0x826)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x568 )), ((0x826)))); |
| 1524 | CSR_WRITE_2(sc, 0x500, 0)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x500 )), ((0)))); |
| 1525 | CSR_WRITE_2(sc, 0x502, 0x30)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x502 )), ((0x30)))); |
| 1526 | |
| 1527 | if (rf->rf_type == BWI_RF_T_BCM20500x2050 && rf->rf_rev <= 5) |
| 1528 | RF_WRITE(mac, 0x51, 0x17)bwi_rf_write((mac), (0x51), (0x17)); |
| 1529 | |
| 1530 | for (i = 0; i < wait_max; ++i) { |
| 1531 | if (CSR_READ_2(sc, 0x50e)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x50e )))) & 0x80) |
| 1532 | break; |
| 1533 | DELAY(10)(*delay_func)(10); |
| 1534 | } |
| 1535 | for (i = 0; i < 10; ++i) { |
| 1536 | if (CSR_READ_2(sc, 0x50e)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x50e )))) & 0x400) |
| 1537 | break; |
| 1538 | DELAY(10)(*delay_func)(10); |
| 1539 | } |
| 1540 | for (i = 0; i < 10; ++i) { |
| 1541 | if ((CSR_READ_2(sc, 0x690)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x690 )))) & 0x100) == 0) |
| 1542 | break; |
| 1543 | DELAY(10)(*delay_func)(10); |
| 1544 | } |
| 1545 | |
| 1546 | if (rf->rf_type == BWI_RF_T_BCM20500x2050 && rf->rf_rev <= 5) |
| 1547 | RF_WRITE(mac, 0x51, 0x37)bwi_rf_write((mac), (0x51), (0x37)); |
| 1548 | #undef PACKET_LEN |
| 1549 | } |
| 1550 | |
| 1551 | void |
| 1552 | bwi_mac_init_tpctl_11bg(struct bwi_mac *mac) |
| 1553 | { |
| 1554 | struct bwi_softc *sc = mac->mac_sc; |
| 1555 | struct bwi_phy *phy = &mac->mac_phy; |
| 1556 | struct bwi_rf *rf = &mac->mac_rf; |
| 1557 | struct bwi_tpctl tpctl_orig; |
| 1558 | int restore_tpctl = 0; |
| 1559 | |
| 1560 | KASSERT(phy->phy_mode != IEEE80211_MODE_11A)((phy->phy_mode != IEEE80211_MODE_11A) ? (void)0 : __assert ("diagnostic ", "/usr/src/sys/dev/ic/bwi.c", 1560, "phy->phy_mode != IEEE80211_MODE_11A" )); |
| 1561 | |
| 1562 | if (BWI_IS_BRCM_BU4306(sc)((sc)->sc_pci_subvid == 0x14e4 && (sc)->sc_pci_subdid == 0x416)) |
| 1563 | return; |
| 1564 | |
| 1565 | PHY_WRITE(mac, 0x28, 0x8018)bwi_phy_write((mac), (0x28), (0x8018)); |
| 1566 | CSR_CLRBITS_2(sc, BWI_BBP_ATTEN, 0x20)((((sc))->sc_mem_bt)->write_2((((sc))->sc_mem_bh), ( ((0x03e6))), ((((((sc))->sc_mem_bt)->read_2((((sc))-> sc_mem_bh), (((0x03e6))))) & ~(0x20))))); |
| 1567 | |
| 1568 | if (phy->phy_mode == IEEE80211_MODE_11G) { |
| 1569 | if ((phy->phy_flags & BWI_PHY_F_LINKED0x2) == 0) |
| 1570 | return; |
| 1571 | PHY_WRITE(mac, 0x47a, 0xc111)bwi_phy_write((mac), (0x47a), (0xc111)); |
| 1572 | } |
| 1573 | if (mac->mac_flags & BWI_MAC_F_TPCTL_INITED0x2) |
| 1574 | return; |
| 1575 | |
| 1576 | if (phy->phy_mode == IEEE80211_MODE_11B && phy->phy_rev >= 2 && |
| 1577 | rf->rf_type == BWI_RF_T_BCM20500x2050) { |
| 1578 | RF_SETBITS(mac, 0x76, 0x84)bwi_rf_write(((mac)), ((0x76)), (bwi_rf_read(((mac)), ((0x76) )) | (0x84))); |
| 1579 | } else { |
| 1580 | struct bwi_tpctl tpctl; |
| 1581 | |
| 1582 | /* Backup original TX power control variables */ |
| 1583 | bcopy(&mac->mac_tpctl, &tpctl_orig, sizeof(tpctl_orig)); |
| 1584 | restore_tpctl = 1; |
| 1585 | |
| 1586 | bcopy(&mac->mac_tpctl, &tpctl, sizeof(tpctl)); |
| 1587 | tpctl.bbp_atten = 11; |
| 1588 | 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 | tpctl.rf_atten = 9; |
| 1595 | |
| 1596 | bwi_mac_set_tpctl_11bg(mac, &tpctl); |
| 1597 | } |
| 1598 | |
| 1599 | bwi_mac_dummy_xmit(mac); |
| 1600 | |
| 1601 | mac->mac_flags |= BWI_MAC_F_TPCTL_INITED0x2; |
| 1602 | rf->rf_base_tssi = PHY_READ(mac, 0x29)bwi_phy_read((mac), (0x29)); |
| 1603 | DPRINTF(1, "%s: base tssi %d\n", sc->sc_dev.dv_xname, rf->rf_base_tssi); |
| 1604 | |
| 1605 | if (abs(rf->rf_base_tssi - rf->rf_idle_tssi) >= 20) { |
| 1606 | printf("%s: base tssi measure failed\n", sc->sc_dev.dv_xname); |
| 1607 | mac->mac_flags |= BWI_MAC_F_TPCTL_ERROR0x40; |
| 1608 | } |
| 1609 | |
| 1610 | if (restore_tpctl) |
| 1611 | bwi_mac_set_tpctl_11bg(mac, &tpctl_orig); |
| 1612 | else |
| 1613 | RF_CLRBITS(mac, 0x76, 0x84)bwi_rf_write(((mac)), ((0x76)), (bwi_rf_read(((mac)), ((0x76) )) & ~(0x84))); |
| 1614 | |
| 1615 | bwi_rf_clear_tssi(mac); |
| 1616 | } |
| 1617 | |
| 1618 | void |
| 1619 | bwi_mac_detach(struct bwi_mac *mac) |
| 1620 | { |
| 1621 | bwi_mac_fw_free(mac); |
| 1622 | } |
| 1623 | |
| 1624 | int |
| 1625 | bwi_get_firmware(const char *name, const uint8_t *ucode, size_t size_ucode, |
| 1626 | size_t *size, size_t *offset) |
| 1627 | { |
| 1628 | int i, nfiles, off = 0, ret = 1; |
| 1629 | struct fwheader *h; |
| 1630 | |
| 1631 | if ((h = malloc(sizeof(struct fwheader), M_DEVBUF2, M_NOWAIT0x0002)) == NULL((void *)0)) |
| 1632 | return (ret); |
| 1633 | |
| 1634 | /* get number of firmware files */ |
| 1635 | bcopy(ucode, &nfiles, sizeof(nfiles)); |
| 1636 | nfiles = ntohl(nfiles)(__uint32_t)(__builtin_constant_p(nfiles) ? (__uint32_t)(((__uint32_t )(nfiles) & 0xff) << 24 | ((__uint32_t)(nfiles) & 0xff00) << 8 | ((__uint32_t)(nfiles) & 0xff0000) >> 8 | ((__uint32_t)(nfiles) & 0xff000000) >> 24) : __swap32md (nfiles)); |
| 1637 | off += sizeof(nfiles); |
| 1638 | |
| 1639 | /* parse header and search the firmware */ |
| 1640 | for (i = 0; i < nfiles && off < size_ucode; i++) { |
| 1641 | bzero(h, sizeof(struct fwheader))__builtin_bzero((h), (sizeof(struct fwheader))); |
| 1642 | bcopy(ucode + off, h, sizeof(struct fwheader)); |
| 1643 | off += sizeof(struct fwheader); |
| 1644 | |
| 1645 | if (strcmp(name, h->filename) == 0) { |
| 1646 | ret = 0; |
| 1647 | *size = ntohl(h->filesize)(__uint32_t)(__builtin_constant_p(h->filesize) ? (__uint32_t )(((__uint32_t)(h->filesize) & 0xff) << 24 | ((__uint32_t )(h->filesize) & 0xff00) << 8 | ((__uint32_t)(h-> filesize) & 0xff0000) >> 8 | ((__uint32_t)(h->filesize ) & 0xff000000) >> 24) : __swap32md(h->filesize) ); |
| 1648 | *offset = ntohl(h->fileoffset)(__uint32_t)(__builtin_constant_p(h->fileoffset) ? (__uint32_t )(((__uint32_t)(h->fileoffset) & 0xff) << 24 | ( (__uint32_t)(h->fileoffset) & 0xff00) << 8 | ((__uint32_t )(h->fileoffset) & 0xff0000) >> 8 | ((__uint32_t )(h->fileoffset) & 0xff000000) >> 24) : __swap32md (h->fileoffset)); |
| 1649 | break; |
| 1650 | } |
| 1651 | } |
| 1652 | |
| 1653 | free(h, M_DEVBUF2, sizeof *h); |
| 1654 | |
| 1655 | return (ret); |
| 1656 | } |
| 1657 | |
| 1658 | int |
| 1659 | 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 | if (fw_len < sizeof(*hdr)) { |
| 1665 | printf("%s: invalid firmware (%s): invalid size %zu\n", |
| 1666 | sc->sc_dev.dv_xname, fw_name, fw_len); |
| 1667 | return (1); |
| 1668 | } |
| 1669 | |
| 1670 | hdr = (const struct bwi_fwhdr *)fw; |
| 1671 | |
| 1672 | if (fw_type != BWI_FW_T_IV'i') { |
| 1673 | /* |
| 1674 | * Don't verify IV's size, it has different meaning |
| 1675 | */ |
| 1676 | if (betoh32(hdr->fw_size)(__uint32_t)(__builtin_constant_p(hdr->fw_size) ? (__uint32_t )(((__uint32_t)(hdr->fw_size) & 0xff) << 24 | (( __uint32_t)(hdr->fw_size) & 0xff00) << 8 | ((__uint32_t )(hdr->fw_size) & 0xff0000) >> 8 | ((__uint32_t) (hdr->fw_size) & 0xff000000) >> 24) : __swap32md (hdr->fw_size)) != fw_len - sizeof(*hdr)) { |
| 1677 | printf("%s: invalid firmware (%s): size mismatch, " |
| 1678 | "fw %u, real %zu\n", |
| 1679 | sc->sc_dev.dv_xname, |
| 1680 | fw_name, |
| 1681 | betoh32(hdr->fw_size)(__uint32_t)(__builtin_constant_p(hdr->fw_size) ? (__uint32_t )(((__uint32_t)(hdr->fw_size) & 0xff) << 24 | (( __uint32_t)(hdr->fw_size) & 0xff00) << 8 | ((__uint32_t )(hdr->fw_size) & 0xff0000) >> 8 | ((__uint32_t) (hdr->fw_size) & 0xff000000) >> 24) : __swap32md (hdr->fw_size)), |
| 1682 | fw_len - sizeof(*hdr)); |
| 1683 | return (1); |
| 1684 | } |
| 1685 | } |
| 1686 | |
| 1687 | if (hdr->fw_type != fw_type) { |
| 1688 | printf("%s: invalid firmware (%s): type mismatch, " |
| 1689 | "fw \'%c\', target \'%c\'\n", |
| 1690 | sc->sc_dev.dv_xname, fw_name, hdr->fw_type, fw_type); |
| 1691 | return (1); |
| 1692 | } |
| 1693 | |
| 1694 | if (hdr->fw_gen != BWI_FW_GEN_11) { |
| 1695 | printf("%s: invalid firmware (%s): wrong generation, " |
| 1696 | "fw %d, target %d\n", |
| 1697 | sc->sc_dev.dv_xname, fw_name, hdr->fw_gen, BWI_FW_GEN_11); |
| 1698 | return (1); |
| 1699 | } |
| 1700 | |
| 1701 | return (0); |
| 1702 | } |
| 1703 | |
| 1704 | int |
| 1705 | bwi_mac_fw_alloc(struct bwi_mac *mac) |
| 1706 | { |
| 1707 | struct bwi_softc *sc = mac->mac_sc; |
| 1708 | char *name = "bwi-airforce"; |
| 1709 | size_t offset; |
| 1710 | char fwname[64]; |
| 1711 | int idx, error; |
| 1712 | |
| 1713 | if (mac->mac_fw == NULL((void *)0)) { |
| 1714 | error = loadfirmware(name, &mac->mac_fw, &mac->mac_fw_size); |
| 1715 | if (error != 0) { |
| 1716 | printf("%s: error %d, could not read firmware %s\n", |
| 1717 | sc->sc_dev.dv_xname, error, name); |
| 1718 | mac->mac_fw = NULL((void *)0); |
| 1719 | return (EIO5); |
| 1720 | } |
| 1721 | } |
| 1722 | |
| 1723 | if (mac->mac_ucode == NULL((void *)0)) { |
| 1724 | snprintf(fwname, sizeof(fwname), "ucode%d.fw", |
| 1725 | mac->mac_revmac_regwin.rw_rev >= 5 ? 5 : mac->mac_revmac_regwin.rw_rev); |
| 1726 | |
| 1727 | error = bwi_get_firmware(fwname, mac->mac_fw, mac->mac_fw_size, |
| 1728 | &mac->mac_ucode_size, &offset); |
| 1729 | if (error != 0) { |
| 1730 | printf("%s: error %d, could not read firmware %s!\n", |
| 1731 | sc->sc_dev.dv_xname, error, fwname); |
| 1732 | return (ENOMEM12); |
| 1733 | } |
| 1734 | 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 | if (bwi_fwimage_is_valid(sc, mac->mac_ucode, |
| 1739 | mac->mac_ucode_size, fwname, BWI_FW_T_UCODE'u')) |
| 1740 | return (EINVAL22); |
| 1741 | } |
| 1742 | |
| 1743 | if (mac->mac_pcm == NULL((void *)0)) { |
| 1744 | snprintf(fwname, sizeof(fwname), "pcm%d.fw", |
| 1745 | mac->mac_revmac_regwin.rw_rev < 5 ? 4 : 5); |
| 1746 | |
| 1747 | error = bwi_get_firmware(fwname, mac->mac_fw, mac->mac_fw_size, |
| 1748 | &mac->mac_pcm_size, &offset); |
| 1749 | if (error != 0) { |
| 1750 | printf("%s: error %d, could not read firmware %s!\n", |
| 1751 | sc->sc_dev.dv_xname, error, fwname); |
| 1752 | return (ENOMEM12); |
| 1753 | } |
| 1754 | 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 | if (bwi_fwimage_is_valid(sc, mac->mac_pcm, |
| 1759 | mac->mac_pcm_size, fwname, BWI_FW_T_PCM'p')) |
| 1760 | return (EINVAL22); |
| 1761 | } |
| 1762 | |
| 1763 | if (mac->mac_iv == NULL((void *)0)) { |
| 1764 | /* TODO: 11A */ |
| 1765 | if (mac->mac_revmac_regwin.rw_rev == 2 || mac->mac_revmac_regwin.rw_rev == 4) { |
| 1766 | idx = 2; |
| 1767 | } else if (mac->mac_revmac_regwin.rw_rev >= 5 && mac->mac_revmac_regwin.rw_rev <= 10) { |
| 1768 | idx = 5; |
| 1769 | } else { |
| 1770 | printf("%s: no suitable IV for MAC rev %d\n", |
| 1771 | sc->sc_dev.dv_xname, mac->mac_revmac_regwin.rw_rev); |
| 1772 | return (ENODEV19); |
| 1773 | } |
| 1774 | |
| 1775 | snprintf(fwname, sizeof(fwname), "b0g0initvals%d.fw", idx); |
| 1776 | |
| 1777 | error = bwi_get_firmware(fwname, mac->mac_fw, mac->mac_fw_size, |
| 1778 | &mac->mac_iv_size, &offset); |
| 1779 | if (error != 0) { |
| 1780 | printf("%s: error %d, could not read firmware %s!\n", |
| 1781 | sc->sc_dev.dv_xname, error, fwname); |
| 1782 | return (ENOMEM12); |
| 1783 | } |
| 1784 | 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 | if (bwi_fwimage_is_valid(sc, mac->mac_iv, |
| 1789 | mac->mac_iv_size, fwname, BWI_FW_T_IV'i')) |
| 1790 | return (EINVAL22); |
| 1791 | } |
| 1792 | |
| 1793 | if (mac->mac_iv_ext == NULL((void *)0)) { |
| 1794 | /* TODO: 11A */ |
| 1795 | if (mac->mac_revmac_regwin.rw_rev == 2 || mac->mac_revmac_regwin.rw_rev == 4 || |
| 1796 | mac->mac_revmac_regwin.rw_rev >= 11) { |
| 1797 | /* No extended IV */ |
| 1798 | goto back; |
| 1799 | } else if (mac->mac_revmac_regwin.rw_rev >= 5 && mac->mac_revmac_regwin.rw_rev <= 10) { |
| 1800 | idx = 5; |
| 1801 | } else { |
| 1802 | printf("%s: no suitable ExtIV for MAC rev %d\n", |
| 1803 | sc->sc_dev.dv_xname, mac->mac_revmac_regwin.rw_rev); |
| 1804 | return (ENODEV19); |
| 1805 | } |
| 1806 | |
| 1807 | snprintf(fwname, sizeof(fwname), "b0g0bsinitvals%d.fw", idx); |
| 1808 | |
| 1809 | error = bwi_get_firmware(fwname, mac->mac_fw, mac->mac_fw_size, |
| 1810 | &mac->mac_iv_ext_size, &offset); |
| 1811 | if (error != 0) { |
| 1812 | printf("%s: error %d, could not read firmware %s!\n", |
| 1813 | sc->sc_dev.dv_xname, error, fwname); |
| 1814 | return (ENOMEM12); |
| 1815 | } |
| 1816 | 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 | if (bwi_fwimage_is_valid(sc, mac->mac_iv_ext, |
| 1821 | mac->mac_iv_ext_size, fwname, BWI_FW_T_IV'i')) |
| 1822 | return (EINVAL22); |
| 1823 | } |
| 1824 | |
| 1825 | back: |
| 1826 | return (0); |
| 1827 | } |
| 1828 | |
| 1829 | void |
| 1830 | bwi_mac_fw_free(struct bwi_mac *mac) |
| 1831 | { |
| 1832 | if (mac->mac_fw != NULL((void *)0)) { |
| 1833 | free(mac->mac_fw, M_DEVBUF2, mac->mac_fw_size); |
| 1834 | mac->mac_fw = NULL((void *)0); |
| 1835 | } |
| 1836 | } |
| 1837 | |
| 1838 | int |
| 1839 | bwi_mac_fw_load(struct bwi_mac *mac) |
| 1840 | { |
| 1841 | 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 | fw = (const uint32_t *)(mac->mac_ucode + BWI_FWHDR_SZsizeof(struct bwi_fwhdr)); |
| 1850 | fw_len = (mac->mac_ucode_size - BWI_FWHDR_SZsizeof(struct bwi_fwhdr)) / sizeof(uint32_t); |
| 1851 | |
| 1852 | CSR_WRITE_4(sc, BWI_MOBJ_CTRL,(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000160 )), ((((0x0 | 0x100) << 16 | (0)))))) |
| 1853 | BWI_MOBJ_CTRL_VAL(BWI_FW_UCODE_MOBJ | BWI_WR_MOBJ_AUTOINC, 0))(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000160 )), ((((0x0 | 0x100) << 16 | (0)))))); |
| 1854 | for (i = 0; i < fw_len; ++i) { |
| 1855 | CSR_WRITE_4(sc, BWI_MOBJ_DATA, betoh32(fw[i]))(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000164 )), (((__uint32_t)(__builtin_constant_p(fw[i]) ? (__uint32_t) (((__uint32_t)(fw[i]) & 0xff) << 24 | ((__uint32_t) (fw[i]) & 0xff00) << 8 | ((__uint32_t)(fw[i]) & 0xff0000) >> 8 | ((__uint32_t)(fw[i]) & 0xff000000 ) >> 24) : __swap32md(fw[i])))))); |
| 1856 | DELAY(10)(*delay_func)(10); |
| 1857 | } |
| 1858 | |
| 1859 | /* |
| 1860 | * Load PCM image |
| 1861 | */ |
| 1862 | fw = (const uint32_t *)(mac->mac_pcm + BWI_FWHDR_SZsizeof(struct bwi_fwhdr)); |
| 1863 | fw_len = (mac->mac_pcm_size - BWI_FWHDR_SZsizeof(struct bwi_fwhdr)) / sizeof(uint32_t); |
| 1864 | |
| 1865 | CSR_WRITE_4(sc, BWI_MOBJ_CTRL,(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000160 )), ((((0x3) << 16 | (0x01ea)))))) |
| 1866 | BWI_MOBJ_CTRL_VAL(BWI_FW_PCM_MOBJ, 0x01ea))(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000160 )), ((((0x3) << 16 | (0x01ea)))))); |
| 1867 | CSR_WRITE_4(sc, BWI_MOBJ_DATA, 0x4000)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000164 )), ((0x4000)))); |
| 1868 | |
| 1869 | CSR_WRITE_4(sc, BWI_MOBJ_CTRL,(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000160 )), ((((0x3) << 16 | (0x01eb)))))) |
| 1870 | BWI_MOBJ_CTRL_VAL(BWI_FW_PCM_MOBJ, 0x01eb))(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000160 )), ((((0x3) << 16 | (0x01eb)))))); |
| 1871 | for (i = 0; i < fw_len; ++i) { |
| 1872 | CSR_WRITE_4(sc, BWI_MOBJ_DATA, betoh32(fw[i]))(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000164 )), (((__uint32_t)(__builtin_constant_p(fw[i]) ? (__uint32_t) (((__uint32_t)(fw[i]) & 0xff) << 24 | ((__uint32_t) (fw[i]) & 0xff00) << 8 | ((__uint32_t)(fw[i]) & 0xff0000) >> 8 | ((__uint32_t)(fw[i]) & 0xff000000 ) >> 24) : __swap32md(fw[i])))))); |
| 1873 | DELAY(10)(*delay_func)(10); |
| 1874 | } |
| 1875 | |
| 1876 | CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_ALL_INTRS)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000128 )), ((0xffffffff)))); |
| 1877 | CSR_WRITE_4(sc, BWI_MAC_STATUS,(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000120 )), (((1U << 1) | (1U << 10) | (1U << 17))) )) |
| 1878 | BWI_MAC_STATUS_UCODE_START |(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000120 )), (((1U << 1) | (1U << 10) | (1U << 17))) )) |
| 1879 | BWI_MAC_STATUS_IHREN |(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000120 )), (((1U << 1) | (1U << 10) | (1U << 17))) )) |
| 1880 | BWI_MAC_STATUS_INFRA)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000120 )), (((1U << 1) | (1U << 10) | (1U << 17))) )); |
| 1881 | |
| 1882 | #define NRETRY 200 |
| 1883 | for (i = 0; i < NRETRY; ++i) { |
| 1884 | uint32_t intr_status; |
| 1885 | |
| 1886 | intr_status = CSR_READ_4(sc, BWI_MAC_INTR_STATUS)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000128 )))); |
| 1887 | if (intr_status == BWI_INTR_READY(1 << 0)) |
| 1888 | break; |
| 1889 | DELAY(10)(*delay_func)(10); |
| 1890 | } |
| 1891 | if (i == NRETRY) { |
| 1892 | printf("%s: firmware (fw & pcm) loading timed out\n", |
| 1893 | sc->sc_dev.dv_xname); |
| 1894 | error = ETIMEDOUT60; |
| 1895 | goto out; |
| 1896 | } |
| 1897 | #undef NRETRY |
| 1898 | |
| 1899 | CSR_READ_4(sc, BWI_MAC_INTR_STATUS)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000128 )))); /* dummy read */ |
| 1900 | |
| 1901 | fw_rev = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWREV)bwi_memobj_read_2((mac), (0x1), (0x0)); |
| 1902 | if (fw_rev > BWI_FW_VERSION3_REVMAX0x128) { |
| 1903 | printf("%s: firmware version 4 is not supported yet\n", |
| 1904 | sc->sc_dev.dv_xname); |
| 1905 | error = ENODEV19; |
| 1906 | 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 | return (error); |
| 1915 | } |
| 1916 | |
| 1917 | int |
| 1918 | bwi_mac_gpio_init(struct bwi_mac *mac) |
| 1919 | { |
| 1920 | struct bwi_softc *sc = mac->mac_sc; |
| 1921 | struct bwi_regwin *old, *gpio_rw; |
| 1922 | uint32_t filt, bits; |
| 1923 | int error; |
| 1924 | |
| 1925 | CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_GPOSEL_MASK)((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x00000120))), ((((((sc))->sc_mem_bt)->read_4((((sc)) ->sc_mem_bh), (((0x00000120))))) & ~((3U << 14)) )))); |
| 1926 | /* TODO: LED */ |
| 1927 | |
| 1928 | CSR_SETBITS_2(sc, BWI_MAC_GPIO_MASK, 0xf)((((sc))->sc_mem_bt)->write_2((((sc))->sc_mem_bh), ( ((0x049e))), ((((((sc))->sc_mem_bt)->read_2((((sc))-> sc_mem_bh), (((0x049e))))) | (0xf))))); |
| 1929 | |
| 1930 | filt = 0x1f; |
| 1931 | bits = 0xf; |
| 1932 | if (sc->sc_bbp_id == BWI_BBPID_BCM43010x4301) { |
| 1933 | filt |= 0x60; |
| 1934 | bits |= 0x60; |
| 1935 | } |
| 1936 | if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9(1 << 1)) { |
| 1937 | CSR_SETBITS_2(sc, BWI_MAC_GPIO_MASK, 0x200)((((sc))->sc_mem_bt)->write_2((((sc))->sc_mem_bh), ( ((0x049e))), ((((((sc))->sc_mem_bt)->read_2((((sc))-> sc_mem_bh), (((0x049e))))) | (0x200))))); |
| 1938 | filt |= 0x200; |
| 1939 | bits |= 0x200; |
| 1940 | } |
| 1941 | |
| 1942 | gpio_rw = BWI_GPIO_REGWIN(sc)(((&(sc)->sc_com_regwin)->rw_flags & 0x1) ? & (sc)->sc_com_regwin : &(sc)->sc_bus_regwin); |
| 1943 | error = bwi_regwin_switch(sc, gpio_rw, &old); |
| 1944 | if (error) |
| 1945 | return (error); |
| 1946 | |
| 1947 | CSR_FILT_SETBITS_4(sc, BWI_GPIO_CTRL, filt, bits)((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x0000006c))), (((((((sc))->sc_mem_bt)->read_4((((sc) )->sc_mem_bh), (((0x0000006c))))) & (filt)) | (bits))) )); |
| 1948 | |
| 1949 | return (bwi_regwin_switch(sc, old, NULL((void *)0))); |
| 1950 | } |
| 1951 | |
| 1952 | int |
| 1953 | bwi_mac_gpio_fini(struct bwi_mac *mac) |
| 1954 | { |
| 1955 | struct bwi_softc *sc = mac->mac_sc; |
| 1956 | struct bwi_regwin *old, *gpio_rw; |
| 1957 | int error; |
| 1958 | |
| 1959 | gpio_rw = BWI_GPIO_REGWIN(sc)(((&(sc)->sc_com_regwin)->rw_flags & 0x1) ? & (sc)->sc_com_regwin : &(sc)->sc_bus_regwin); |
| 1960 | error = bwi_regwin_switch(sc, gpio_rw, &old); |
| 1961 | if (error) |
| 1962 | return (error); |
| 1963 | |
| 1964 | CSR_WRITE_4(sc, BWI_GPIO_CTRL, 0)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x0000006c )), ((0)))); |
| 1965 | |
| 1966 | return (bwi_regwin_switch(sc, old, NULL((void *)0))); |
| 1967 | } |
| 1968 | |
| 1969 | int |
| 1970 | bwi_mac_fw_load_iv(struct bwi_mac *mac, uint8_t *fw, size_t fw_len) |
| 1971 | { |
| 1972 | 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 | hdr = (const struct bwi_fwhdr *)fw; |
| 1979 | n = betoh32(hdr->fw_iv_cnt)(__uint32_t)(__builtin_constant_p(hdr->fw_size) ? (__uint32_t )(((__uint32_t)(hdr->fw_size) & 0xff) << 24 | (( __uint32_t)(hdr->fw_size) & 0xff00) << 8 | ((__uint32_t )(hdr->fw_size) & 0xff0000) >> 8 | ((__uint32_t) (hdr->fw_size) & 0xff000000) >> 24) : __swap32md (hdr->fw_size)); |
| 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 | iv_img_size = fw_len - sizeof(*hdr); |
| 1984 | |
| 1985 | /* Locate the first IV */ |
| 1986 | iv = (const struct bwi_fw_iv *)(fw + sizeof(*hdr)); |
| 1987 | |
| 1988 | for (i = 0; i < n; ++i) { |
| 1989 | uint16_t iv_ofs, ofs; |
| 1990 | int sz = 0; |
| 1991 | |
| 1992 | if (iv_img_size < sizeof(iv->iv_ofs)) { |
| 1993 | printf("%s: invalid IV image, ofs\n", |
| 1994 | sc->sc_dev.dv_xname); |
| 1995 | return (EINVAL22); |
| 1996 | } |
| 1997 | iv_img_size -= sizeof(iv->iv_ofs); |
| 1998 | sz += sizeof(iv->iv_ofs); |
| 1999 | |
| 2000 | iv_ofs = betoh16(iv->iv_ofs)(__uint16_t)(__builtin_constant_p(iv->iv_ofs) ? (__uint16_t )(((__uint16_t)(iv->iv_ofs) & 0xffU) << 8 | ((__uint16_t )(iv->iv_ofs) & 0xff00U) >> 8) : __swap16md(iv-> iv_ofs)); |
| 2001 | |
| 2002 | ofs = __SHIFTOUT(iv_ofs, BWI_FW_IV_OFS_MASK)(((iv_ofs) & (0x7fff)) / ((((0x7fff) - 1) & (0x7fff)) ^ (0x7fff))); |
| 2003 | if (ofs >= 0x1000) { |
| 2004 | printf("%s: invalid ofs (0x%04x) for %dth iv\n", |
| 2005 | sc->sc_dev.dv_xname, ofs, i); |
| 2006 | return (EINVAL22); |
| 2007 | } |
| 2008 | |
| 2009 | if (iv_ofs & BWI_FW_IV_IS_32BIT(1 << 15)) { |
| 2010 | uint32_t val32; |
| 2011 | |
| 2012 | if (iv_img_size < sizeof(iv->iv_val.val32)) { |
| 2013 | printf("%s: invalid IV image, val32\n", |
| 2014 | sc->sc_dev.dv_xname); |
| 2015 | return (EINVAL22); |
| 2016 | } |
| 2017 | iv_img_size -= sizeof(iv->iv_val.val32); |
| 2018 | sz += sizeof(iv->iv_val.val32); |
| 2019 | |
| 2020 | val32 = betoh32(iv->iv_val.val32)(__uint32_t)(__builtin_constant_p(iv->iv_val.val32) ? (__uint32_t )(((__uint32_t)(iv->iv_val.val32) & 0xff) << 24 | ((__uint32_t)(iv->iv_val.val32) & 0xff00) << 8 | ((__uint32_t)(iv->iv_val.val32) & 0xff0000) >> 8 | ((__uint32_t)(iv->iv_val.val32) & 0xff000000) >> 24) : __swap32md(iv->iv_val.val32)); |
| 2021 | CSR_WRITE_4(sc, ofs, val32)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((ofs )), ((val32)))); |
| 2022 | } else { |
| 2023 | uint16_t val16; |
| 2024 | |
| 2025 | if (iv_img_size < sizeof(iv->iv_val.val16)) { |
| 2026 | printf("%s: invalid IV image, val16\n", |
| 2027 | sc->sc_dev.dv_xname); |
| 2028 | return (EINVAL22); |
| 2029 | } |
| 2030 | iv_img_size -= sizeof(iv->iv_val.val16); |
| 2031 | sz += sizeof(iv->iv_val.val16); |
| 2032 | |
| 2033 | val16 = betoh16(iv->iv_val.val16)(__uint16_t)(__builtin_constant_p(iv->iv_val.val16) ? (__uint16_t )(((__uint16_t)(iv->iv_val.val16) & 0xffU) << 8 | ((__uint16_t)(iv->iv_val.val16) & 0xff00U) >> 8 ) : __swap16md(iv->iv_val.val16)); |
| 2034 | CSR_WRITE_2(sc, ofs, val16)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((ofs )), ((val16)))); |
| 2035 | } |
| 2036 | |
| 2037 | iv = (const struct bwi_fw_iv *)((const uint8_t *)iv + sz); |
| 2038 | } |
| 2039 | |
| 2040 | if (iv_img_size != 0) { |
| 2041 | printf("%s: invalid IV image, size left %d\n", |
| 2042 | sc->sc_dev.dv_xname, iv_img_size); |
| 2043 | return (EINVAL22); |
| 2044 | } |
| 2045 | |
| 2046 | return (0); |
| 2047 | } |
| 2048 | |
| 2049 | int |
| 2050 | bwi_mac_fw_init(struct bwi_mac *mac) |
| 2051 | { |
| 2052 | struct bwi_softc *sc = mac->mac_sc; |
| 2053 | int error; |
| 2054 | |
| 2055 | error = bwi_mac_fw_load_iv(mac, mac->mac_iv, mac->mac_iv_size); |
| 2056 | if (error) { |
| 2057 | printf("%s: load IV failed\n", sc->sc_dev.dv_xname); |
| 2058 | return (error); |
| 2059 | } |
| 2060 | |
| 2061 | if (mac->mac_iv_ext != NULL((void *)0)) { |
| 2062 | error = bwi_mac_fw_load_iv(mac, mac->mac_iv_ext, |
| 2063 | mac->mac_iv_ext_size); |
| 2064 | if (error) |
| 2065 | printf("%s: load ExtIV failed\n", sc->sc_dev.dv_xname); |
| 2066 | } |
| 2067 | |
| 2068 | return (error); |
| 2069 | } |
| 2070 | |
| 2071 | void |
| 2072 | bwi_mac_opmode_init(struct bwi_mac *mac) |
| 2073 | { |
| 2074 | struct bwi_softc *sc = mac->mac_sc; |
| 2075 | struct ieee80211com *ic = &sc->sc_ic; |
| 2076 | uint32_t mac_status; |
| 2077 | uint16_t pre_tbtt; |
| 2078 | |
| 2079 | CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_INFRA)((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x00000120))), ((((((sc))->sc_mem_bt)->read_4((((sc)) ->sc_mem_bh), (((0x00000120))))) & ~((1U << 17)) )))); |
| 2080 | CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_INFRA)((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x00000120))), ((((((sc))->sc_mem_bt)->read_4((((sc)) ->sc_mem_bh), (((0x00000120))))) | ((1U << 17)))))); |
| 2081 | CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PASS_BCN)((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x00000120))), ((((((sc))->sc_mem_bt)->read_4((((sc)) ->sc_mem_bh), (((0x00000120))))) | ((1U << 20)))))); |
| 2082 | |
| 2083 | /* Set probe resp timeout to infinite */ |
| 2084 | MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_PROBE_RESP_TO, 0)bwi_memobj_write_2((mac), (0x1), (0x74), (0)); |
| 2085 | |
| 2086 | /* |
| 2087 | * TODO: factor out following part |
| 2088 | */ |
| 2089 | |
| 2090 | mac_status = CSR_READ_4(sc, BWI_MAC_STATUS)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000120 )))); |
| 2091 | mac_status &= ~(BWI_MAC_STATUS_OPMODE_HOSTAP(1U << 18) | |
| 2092 | BWI_MAC_STATUS_PASS_CTL(1U << 22) | |
| 2093 | BWI_MAC_STATUS_PASS_BADPLCP(1U << 21) | |
| 2094 | BWI_MAC_STATUS_PASS_BADFCS(1U << 23) | |
| 2095 | BWI_MAC_STATUS_PROMISC(1U << 24)); |
| 2096 | mac_status |= BWI_MAC_STATUS_INFRA(1U << 17); |
| 2097 | |
| 2098 | /* Always turn on PROMISC on old hardware */ |
| 2099 | if (mac->mac_revmac_regwin.rw_rev < 5) |
| 2100 | mac_status |= BWI_MAC_STATUS_PROMISC(1U << 24); |
| 2101 | |
| 2102 | switch (ic->ic_opmode) { |
| 2103 | #ifndef IEEE80211_STA_ONLY |
| 2104 | case IEEE80211_M_IBSS: |
| 2105 | mac_status &= ~BWI_MAC_STATUS_INFRA(1U << 17); |
| 2106 | break; |
| 2107 | case IEEE80211_M_HOSTAP: |
| 2108 | mac_status |= BWI_MAC_STATUS_OPMODE_HOSTAP(1U << 18); |
| 2109 | 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(1U << 22) | |
| 2115 | BWI_MAC_STATUS_PASS_BADPLCP(1U << 21) | |
| 2116 | BWI_MAC_STATUS_PASS_BADFCS(1U << 23); |
| 2117 | #else |
| 2118 | mac_status |= BWI_MAC_STATUS_PASS_CTL(1U << 22); |
| 2119 | #endif |
| 2120 | /* Promisc? */ |
| 2121 | break; |
| 2122 | default: |
| 2123 | break; |
| 2124 | } |
| 2125 | |
| 2126 | if (ic->ic_ific_ac.ac_if.if_flags & IFF_PROMISC0x100) |
| 2127 | mac_status |= BWI_MAC_STATUS_PROMISC(1U << 24); |
| 2128 | |
| 2129 | CSR_WRITE_4(sc, BWI_MAC_STATUS, mac_status)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000120 )), ((mac_status)))); |
| 2130 | |
| 2131 | #ifndef IEEE80211_STA_ONLY |
| 2132 | if (ic->ic_opmode != IEEE80211_M_IBSS && |
| 2133 | ic->ic_opmode != IEEE80211_M_HOSTAP) { |
| 2134 | #endif |
| 2135 | if (sc->sc_bbp_id == BWI_BBPID_BCM43060x4306 && sc->sc_bbp_rev == 3) |
| 2136 | pre_tbtt = 100; |
| 2137 | else |
| 2138 | pre_tbtt = 50; |
| 2139 | #ifndef IEEE80211_STA_ONLY |
| 2140 | } else |
| 2141 | pre_tbtt = 2; |
| 2142 | #endif |
| 2143 | CSR_WRITE_2(sc, BWI_MAC_PRE_TBTT, pre_tbtt)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x0612 )), ((pre_tbtt)))); |
| 2144 | } |
| 2145 | |
| 2146 | void |
| 2147 | bwi_mac_hostflags_init(struct bwi_mac *mac) |
| 2148 | { |
| 2149 | struct bwi_softc *sc = mac->mac_sc; |
| 2150 | struct bwi_phy *phy = &mac->mac_phy; |
| 2151 | struct bwi_rf *rf = &mac->mac_rf; |
| 2152 | uint64_t host_flags; |
| 2153 | |
| 2154 | if (phy->phy_mode == IEEE80211_MODE_11A) |
| 2155 | return; |
| 2156 | |
| 2157 | host_flags = HFLAGS_READ(mac)bwi_hostflags_read((mac)); |
| 2158 | host_flags |= BWI_HFLAG_SYM_WA0x2ULL; |
| 2159 | |
| 2160 | if (phy->phy_mode == IEEE80211_MODE_11G) { |
| 2161 | if (phy->phy_rev == 1) |
| 2162 | host_flags |= BWI_HFLAG_GDC_WA0x20ULL; |
| 2163 | if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9(1 << 1)) |
| 2164 | host_flags |= BWI_HFLAG_OFDM_PA0x40ULL; |
| 2165 | } else if (phy->phy_mode == IEEE80211_MODE_11B) { |
| 2166 | if (phy->phy_rev >= 2 && rf->rf_type == BWI_RF_T_BCM20500x2050) |
| 2167 | host_flags &= ~BWI_HFLAG_GDC_WA0x20ULL; |
| 2168 | } else { |
| 2169 | panic("unknown PHY mode %u", phy->phy_mode); |
| 2170 | } |
| 2171 | |
| 2172 | HFLAGS_WRITE(mac, host_flags)bwi_hostflags_write((mac), (host_flags)); |
| 2173 | } |
| 2174 | |
| 2175 | void |
| 2176 | bwi_mac_bss_param_init(struct bwi_mac *mac) |
| 2177 | { |
| 2178 | struct bwi_softc *sc = mac->mac_sc; |
| 2179 | struct bwi_phy *phy = &mac->mac_phy; |
| 2180 | struct bwi_retry_lim lim; |
| 2181 | uint16_t cw_min; |
| 2182 | |
| 2183 | /* |
| 2184 | * Set short/long retry limits |
| 2185 | */ |
| 2186 | bzero(&lim, sizeof(lim))__builtin_bzero((&lim), (sizeof(lim))); |
| 2187 | lim.shretry = BWI_SHRETRY7; |
| 2188 | lim.shretry_fb = BWI_SHRETRY_FB3; |
| 2189 | lim.lgretry = BWI_LGRETRY4; |
| 2190 | lim.lgretry_fb = BWI_LGRETRY_FB2; |
| 2191 | 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 | MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_PROBE_RESP_TO, 1)bwi_memobj_write_2((mac), (0x1), (0x74), (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 | bwi_mac_set_ackrates(mac, &sc->sc_ic.ic_sup_rates[phy->phy_mode]); |
| 2208 | |
| 2209 | /* |
| 2210 | * Set CW min |
| 2211 | */ |
| 2212 | if (phy->phy_mode == IEEE80211_MODE_11B) |
| 2213 | cw_min = IEEE80211_CW_MIN_031; |
| 2214 | else |
| 2215 | cw_min = IEEE80211_CW_MIN_115; |
| 2216 | MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_CWMIN, cw_min)bwi_memobj_write_2((mac), (0x2), (0xc), (cw_min)); |
| 2217 | |
| 2218 | /* |
| 2219 | * Set CW max |
| 2220 | */ |
| 2221 | MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_CWMAX,bwi_memobj_write_2((mac), (0x2), (0x10), (1023)) |
| 2222 | IEEE80211_CW_MAX)bwi_memobj_write_2((mac), (0x2), (0x10), (1023)); |
| 2223 | } |
| 2224 | |
| 2225 | void |
| 2226 | bwi_mac_set_retry_lim(struct bwi_mac *mac, const struct bwi_retry_lim *lim) |
| 2227 | { |
| 2228 | /* Short/Long retry limit */ |
| 2229 | MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_SHRETRY,bwi_memobj_write_2((mac), (0x2), (0x18), (lim->shretry)) |
| 2230 | lim->shretry)bwi_memobj_write_2((mac), (0x2), (0x18), (lim->shretry)); |
| 2231 | MOBJ_WRITE_2(mac, BWI_80211_MOBJ, BWI_80211_MOBJ_LGRETRY,bwi_memobj_write_2((mac), (0x2), (0x1c), (lim->lgretry)) |
| 2232 | lim->lgretry)bwi_memobj_write_2((mac), (0x2), (0x1c), (lim->lgretry)); |
| 2233 | |
| 2234 | /* Short/Long retry fallback limit */ |
| 2235 | MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_SHRETRY_FB,bwi_memobj_write_2((mac), (0x1), (0x44), (lim->shretry_fb) ) |
| 2236 | lim->shretry_fb)bwi_memobj_write_2((mac), (0x1), (0x44), (lim->shretry_fb) ); |
| 2237 | MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_LGRETEY_FB,bwi_memobj_write_2((mac), (0x1), (0x46), (lim->lgretry_fb) ) |
| 2238 | lim->lgretry_fb)bwi_memobj_write_2((mac), (0x1), (0x46), (lim->lgretry_fb) ); |
| 2239 | } |
| 2240 | |
| 2241 | void |
| 2242 | bwi_mac_set_ackrates(struct bwi_mac *mac, const struct ieee80211_rateset *rs) |
| 2243 | { |
| 2244 | struct bwi_softc *sc; |
| 2245 | int i; |
| 2246 | |
| 2247 | sc = mac->mac_sc; |
| 2248 | |
| 2249 | DPRINTF(1, "%s: %s\n", sc->sc_dev.dv_xname, __func__); |
| 2250 | |
| 2251 | /* XXX not standard conforming */ |
| 2252 | for (i = 0; i < rs->rs_nrates; ++i) { |
| 2253 | enum bwi_modtype modtype; |
| 2254 | uint16_t ofs; |
| 2255 | |
| 2256 | modtype = bwi_rate2modtype(rs->rs_rates[i]); |
| 2257 | switch (modtype) { |
| 2258 | case IEEE80211_MODTYPE_DS: |
| 2259 | ofs = 0x4c0; |
| 2260 | ofs += (ieee80211_rate2plcp(rs->rs_rates[i], |
| 2261 | IEEE80211_MODE_11B) & 0xf) * 2; |
| 2262 | break; |
| 2263 | case IEEE80211_MODTYPE_OFDM: |
| 2264 | ofs = 0x480; |
| 2265 | ofs += (ieee80211_rate2plcp(rs->rs_rates[i], |
| 2266 | IEEE80211_MODE_11G) & 0xf) * 2; |
| 2267 | break; |
| 2268 | default: |
| 2269 | panic("unsupported modtype %u", modtype); |
| 2270 | } |
| 2271 | |
| 2272 | MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, ofs + 0x20,bwi_memobj_write_2((mac), (0x1), (ofs + 0x20), (bwi_memobj_read_2 ((mac), (0x1), (ofs)))) |
| 2273 | MOBJ_READ_2(mac, BWI_COMM_MOBJ, ofs))bwi_memobj_write_2((mac), (0x1), (ofs + 0x20), (bwi_memobj_read_2 ((mac), (0x1), (ofs)))); |
| 2274 | } |
| 2275 | } |
| 2276 | |
| 2277 | int |
| 2278 | bwi_mac_start(struct bwi_mac *mac) |
| 2279 | { |
| 2280 | struct bwi_softc *sc = mac->mac_sc; |
| 2281 | |
| 2282 | CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_ENABLE)((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x00000120))), ((((((sc))->sc_mem_bt)->read_4((((sc)) ->sc_mem_bh), (((0x00000120))))) | ((1U << 0)))))); |
| 2283 | CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, BWI_INTR_READY)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000128 )), (((1 << 0))))); |
| 2284 | |
| 2285 | /* Flush pending bus writes */ |
| 2286 | CSR_READ_4(sc, BWI_MAC_STATUS)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000120 )))); |
| 2287 | CSR_READ_4(sc, BWI_MAC_INTR_STATUS)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000128 )))); |
| 2288 | |
| 2289 | return (bwi_mac_config_ps(mac)); |
| 2290 | } |
| 2291 | |
| 2292 | int |
| 2293 | bwi_mac_stop(struct bwi_mac *mac) |
| 2294 | { |
| 2295 | struct bwi_softc *sc = mac->mac_sc; |
| 2296 | int error, i; |
| 2297 | |
| 2298 | error = bwi_mac_config_ps(mac); |
| 2299 | if (error) |
| 2300 | return (error); |
| 2301 | |
| 2302 | CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_ENABLE)((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x00000120))), ((((((sc))->sc_mem_bt)->read_4((((sc)) ->sc_mem_bh), (((0x00000120))))) & ~((1U << 0))) ))); |
| 2303 | |
| 2304 | /* Flush pending bus write */ |
| 2305 | CSR_READ_4(sc, BWI_MAC_STATUS)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000120 )))); |
| 2306 | |
| 2307 | #define NRETRY 10000 |
| 2308 | for (i = 0; i < NRETRY; ++i) { |
| 2309 | if (CSR_READ_4(sc, BWI_MAC_INTR_STATUS)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000128 )))) & BWI_INTR_READY(1 << 0)) |
| 2310 | break; |
| 2311 | DELAY(1)(*delay_func)(1); |
| 2312 | } |
| 2313 | if (i == NRETRY) { |
| 2314 | printf("%s: can't stop MAC\n", sc->sc_dev.dv_xname); |
| 2315 | return (ETIMEDOUT60); |
| 2316 | } |
| 2317 | #undef NRETRY |
| 2318 | |
| 2319 | return (0); |
| 2320 | } |
| 2321 | |
| 2322 | int |
| 2323 | bwi_mac_config_ps(struct bwi_mac *mac) |
| 2324 | { |
| 2325 | struct bwi_softc *sc = mac->mac_sc; |
| 2326 | uint32_t status; |
| 2327 | |
| 2328 | status = CSR_READ_4(sc, BWI_MAC_STATUS)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000120 )))); |
| 2329 | |
| 2330 | status &= ~BWI_MAC_STATUS_HW_PS(1U << 25); |
| 2331 | status |= BWI_MAC_STATUS_WAKEUP(1U << 26); |
| 2332 | CSR_WRITE_4(sc, BWI_MAC_STATUS, status)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000120 )), ((status)))); |
| 2333 | |
| 2334 | /* Flush pending bus write */ |
| 2335 | CSR_READ_4(sc, BWI_MAC_STATUS)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000120 )))); |
| 2336 | |
| 2337 | if (mac->mac_revmac_regwin.rw_rev >= 5) { |
| 2338 | int i; |
| 2339 | |
| 2340 | #define NRETRY 100 |
| 2341 | for (i = 0; i < NRETRY; ++i) { |
| 2342 | if (MOBJ_READ_2(mac, BWI_COMM_MOBJ,bwi_memobj_read_2((mac), (0x1), (0x40)) |
| 2343 | BWI_COMM_MOBJ_UCODE_STATE)bwi_memobj_read_2((mac), (0x1), (0x40)) != BWI_UCODE_STATE_PS4) |
| 2344 | break; |
| 2345 | DELAY(10)(*delay_func)(10); |
| 2346 | } |
| 2347 | if (i == NRETRY) { |
| 2348 | printf("%s: config PS failed\n", sc->sc_dev.dv_xname); |
| 2349 | return (ETIMEDOUT60); |
| 2350 | } |
| 2351 | #undef NRETRY |
| 2352 | } |
| 2353 | return (0); |
| 2354 | } |
| 2355 | |
| 2356 | void |
| 2357 | bwi_mac_reset_hwkeys(struct bwi_mac *mac) |
| 2358 | { |
| 2359 | /* TODO: firmware crypto */ |
| 2360 | MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_KEYTABLE_OFS)bwi_memobj_read_2((mac), (0x1), (0x56)); |
| 2361 | } |
| 2362 | |
| 2363 | void |
| 2364 | bwi_mac_shutdown(struct bwi_mac *mac) |
| 2365 | { |
| 2366 | struct bwi_softc *sc = mac->mac_sc; |
| 2367 | int i; |
| 2368 | |
| 2369 | if (mac->mac_flags & BWI_MAC_F_HAS_TXSTATS0x4) |
| 2370 | sc->sc_free_txstats(sc); |
| 2371 | |
| 2372 | sc->sc_free_rx_ring(sc); |
| 2373 | |
| 2374 | for (i = 0; i < BWI_TX_NRING6; ++i) |
| 2375 | sc->sc_free_tx_ring(sc, i); |
| 2376 | |
| 2377 | bwi_rf_off(mac); |
| 2378 | |
| 2379 | /* TODO: LED */ |
| 2380 | |
| 2381 | bwi_mac_gpio_fini(mac); |
| 2382 | |
| 2383 | bwi_rf_off(mac); /* XXX again */ |
| 2384 | CSR_WRITE_2(sc, BWI_BBP_ATTEN, BWI_BBP_ATTEN_MAGIC)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03e6 )), ((0x00f4)))); |
| 2385 | bwi_regwin_disable(sc, &mac->mac_regwin, 0); |
| 2386 | |
| 2387 | mac->mac_flags &= ~BWI_MAC_F_INITED0x8; |
| 2388 | } |
| 2389 | |
| 2390 | int |
| 2391 | bwi_mac_get_property(struct bwi_mac *mac) |
| 2392 | { |
| 2393 | 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 | val = CSR_READ_4(sc, BWI_MAC_STATUS)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000120 )))); |
| 2401 | if (val & BWI_MAC_STATUS_BSWAP(1U << 16)) { |
| 2402 | DPRINTF(1, "%s: need byte swap\n", sc->sc_dev.dv_xname); |
| 2403 | mac->mac_flags |= BWI_MAC_F_BSWAP0x1; |
| 2404 | } |
| 2405 | |
| 2406 | /* |
| 2407 | * DMA address space |
| 2408 | */ |
| 2409 | old_bus_space = sc->sc_bus_space; |
| 2410 | |
| 2411 | val = CSR_READ_4(sc, BWI_STATE_HI)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000f9c )))); |
| 2412 | if (__SHIFTOUT(val, BWI_STATE_HI_FLAGS_MASK)(((val) & (0x1fff0000)) / ((((0x1fff0000) - 1) & (0x1fff0000 )) ^ (0x1fff0000))) & |
| 2413 | BWI_STATE_HI_FLAG_64BIT0x1000) { |
| 2414 | /* 64bit address */ |
| 2415 | sc->sc_bus_space = BWI_BUS_SPACE_64BIT; |
| 2416 | printf(": 64bit bus space not supported\n"); |
| 2417 | return (ENODEV19); |
| 2418 | } else { |
| 2419 | uint32_t txrx_reg = BWI_TXRX_CTRL_BASE0x200 + BWI_TX32_CTRL0x0; |
| 2420 | |
| 2421 | CSR_WRITE_4(sc, txrx_reg, BWI_TXRX32_CTRL_ADDRHI_MASK)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((txrx_reg )), ((0x00030000)))); |
| 2422 | if (CSR_READ_4(sc, txrx_reg)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((txrx_reg )))) & BWI_TXRX32_CTRL_ADDRHI_MASK0x00030000) { |
| 2423 | /* 32bit address */ |
| 2424 | sc->sc_bus_space = BWI_BUS_SPACE_32BIT; |
| 2425 | DPRINTF(1, "%s: 32bit bus space\n", |
| 2426 | sc->sc_dev.dv_xname); |
| 2427 | } else { |
| 2428 | /* 30bit address */ |
| 2429 | 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 | if (old_bus_space != 0 && old_bus_space != sc->sc_bus_space) { |
| 2436 | printf("%s: MACs bus space mismatch!\n", sc->sc_dev.dv_xname); |
| 2437 | return (ENXIO6); |
| 2438 | } |
| 2439 | |
| 2440 | return (0); |
| 2441 | } |
| 2442 | |
| 2443 | void |
| 2444 | bwi_mac_updateslot(struct bwi_mac *mac, int shslot) |
| 2445 | { |
| 2446 | struct bwi_softc *sc; |
| 2447 | uint16_t slot_time; |
| 2448 | |
| 2449 | sc = mac->mac_sc; |
Value stored to 'sc' is never read | |
| 2450 | |
| 2451 | DPRINTF(1, "%s: %s\n", sc->sc_dev.dv_xname, __func__); |
| 2452 | |
| 2453 | if (mac->mac_phy.phy_mode == IEEE80211_MODE_11B) |
| 2454 | return; |
| 2455 | |
| 2456 | if (shslot) |
| 2457 | slot_time = IEEE80211_DUR_DS_SHSLOT9; |
| 2458 | else |
| 2459 | slot_time = IEEE80211_DUR_DS_SLOT20; |
| 2460 | |
| 2461 | CSR_WRITE_2(mac->mac_sc, BWI_MAC_SLOTTIME,(((mac->mac_sc)->sc_mem_bt)->write_2(((mac->mac_sc )->sc_mem_bh), ((0x0684)), ((slot_time + 510)))) |
| 2462 | slot_time + BWI_MAC_SLOTTIME_ADJUST)(((mac->mac_sc)->sc_mem_bt)->write_2(((mac->mac_sc )->sc_mem_bh), ((0x0684)), ((slot_time + 510)))); |
| 2463 | MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_SLOTTIME, slot_time)bwi_memobj_write_2((mac), (0x1), (0x10), (slot_time)); |
| 2464 | } |
| 2465 | |
| 2466 | int |
| 2467 | bwi_mac_attach(struct bwi_softc *sc, int id, uint8_t rev) |
| 2468 | { |
| 2469 | struct bwi_mac *mac; |
| 2470 | int i; |
| 2471 | |
| 2472 | KASSERT(sc->sc_nmac <= BWI_MAC_MAX && sc->sc_nmac >= 0)((sc->sc_nmac <= 2 && sc->sc_nmac >= 0) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c" , 2472, "sc->sc_nmac <= BWI_MAC_MAX && sc->sc_nmac >= 0" )); |
| 2473 | |
| 2474 | if (sc->sc_nmac == BWI_MAC_MAX2) { |
| 2475 | printf("%s: too many MACs\n", sc->sc_dev.dv_xname); |
| 2476 | return (0); |
| 2477 | } |
| 2478 | |
| 2479 | /* |
| 2480 | * More than one MAC is only supported by BCM4309 |
| 2481 | */ |
| 2482 | if (sc->sc_nmac != 0 && |
| 2483 | sc->sc_pci_did != PCI_PRODUCT_BROADCOM_BCM43090x4324) { |
| 2484 | DPRINTF(1, "%s: ignore second MAC\n", sc->sc_dev.dv_xname); |
| 2485 | return (0); |
| 2486 | } |
| 2487 | |
| 2488 | mac = &sc->sc_mac[sc->sc_nmac]; |
| 2489 | |
| 2490 | /* XXX will this happen? */ |
| 2491 | if (BWI_REGWIN_EXIST(&mac->mac_regwin)((&mac->mac_regwin)->rw_flags & 0x1)) { |
| 2492 | printf("%s: %dth MAC already attached\n", |
| 2493 | sc->sc_dev.dv_xname, sc->sc_nmac); |
| 2494 | return (0); |
| 2495 | } |
| 2496 | |
| 2497 | /* |
| 2498 | * Test whether the revision of this MAC is supported |
| 2499 | */ |
| 2500 | for (i = 0; i < nitems(bwi_sup_macrev)(sizeof((bwi_sup_macrev)) / sizeof((bwi_sup_macrev)[0])); ++i) { |
| 2501 | if (bwi_sup_macrev[i] == rev) |
| 2502 | break; |
| 2503 | } |
| 2504 | if (i == nitems(bwi_sup_macrev)(sizeof((bwi_sup_macrev)) / sizeof((bwi_sup_macrev)[0]))) { |
| 2505 | printf("%s: MAC rev %u is not supported\n", |
| 2506 | sc->sc_dev.dv_xname, rev); |
| 2507 | return (ENXIO6); |
| 2508 | } |
| 2509 | |
| 2510 | BWI_CREATE_MAC(mac, sc, id, rev)do { do { (&(mac)->mac_regwin)->rw_flags = 0x1; (& (mac)->mac_regwin)->rw_type = (0x812); (&(mac)-> mac_regwin)->rw_id = ((id)); (&(mac)->mac_regwin)-> rw_rev = ((rev)); } while (0); (mac)->mac_sc = (sc); } while (0); |
| 2511 | sc->sc_nmac++; |
| 2512 | |
| 2513 | if (mac->mac_revmac_regwin.rw_rev < 5) { |
| 2514 | mac->mac_flags |= BWI_MAC_F_HAS_TXSTATS0x4; |
| 2515 | DPRINTF(1, "%s: has TX stats\n", sc->sc_dev.dv_xname); |
| 2516 | } else { |
| 2517 | mac->mac_flags |= BWI_MAC_F_PHYE_RESET0x80; |
| 2518 | } |
| 2519 | |
| 2520 | return (0); |
| 2521 | } |
| 2522 | |
| 2523 | void |
| 2524 | bwi_mac_balance_atten(int *bbp_atten0, int *rf_atten0) |
| 2525 | { |
| 2526 | int bbp_atten, rf_atten, rf_atten_lim = -1; |
| 2527 | |
| 2528 | bbp_atten = *bbp_atten0; |
| 2529 | 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 | if (rf_atten < 0) |
| 2544 | rf_atten_lim = 0; |
| 2545 | else if (rf_atten > BWI_RF_ATTEN_MAX09) |
| 2546 | rf_atten_lim = BWI_RF_ATTEN_MAX09; |
| 2547 | |
| 2548 | if (rf_atten_lim >= 0) { |
| 2549 | bbp_atten += (BWI_RF_ATTEN_FACTOR4 * (rf_atten - rf_atten_lim)); |
| 2550 | rf_atten = rf_atten_lim; |
| 2551 | } |
| 2552 | |
| 2553 | /* |
| 2554 | * If possible, use RF attenuation to balance BBP attenuation |
| 2555 | * NOTE: RF attenuation is still kept within range. |
| 2556 | */ |
| 2557 | while (rf_atten < BWI_RF_ATTEN_MAX09 && bbp_atten > BWI_BBP_ATTEN_MAX11) { |
| 2558 | bbp_atten -= BWI_RF_ATTEN_FACTOR4; |
| 2559 | ++rf_atten; |
| 2560 | } |
| 2561 | while (rf_atten > 0 && bbp_atten < 0) { |
| 2562 | bbp_atten += BWI_RF_ATTEN_FACTOR4; |
| 2563 | --rf_atten; |
| 2564 | } |
| 2565 | |
| 2566 | /* RF attenuation MUST be within range */ |
| 2567 | KASSERT(rf_atten >= 0 && rf_atten <= BWI_RF_ATTEN_MAX0)((rf_atten >= 0 && rf_atten <= 9) ? (void)0 : __assert ("diagnostic ", "/usr/src/sys/dev/ic/bwi.c", 2567, "rf_atten >= 0 && rf_atten <= BWI_RF_ATTEN_MAX0" )); |
| 2568 | |
| 2569 | /* |
| 2570 | * Clamp BBP attenuation |
| 2571 | */ |
| 2572 | if (bbp_atten < 0) |
| 2573 | bbp_atten = 0; |
| 2574 | else if (bbp_atten > BWI_BBP_ATTEN_MAX11) |
| 2575 | bbp_atten = BWI_BBP_ATTEN_MAX11; |
| 2576 | |
| 2577 | *rf_atten0 = rf_atten; |
| 2578 | *bbp_atten0 = bbp_atten; |
| 2579 | } |
| 2580 | |
| 2581 | void |
| 2582 | bwi_mac_adjust_tpctl(struct bwi_mac *mac, int rf_atten_adj, int bbp_atten_adj) |
| 2583 | { |
| 2584 | struct bwi_softc *sc = mac->mac_sc; |
| 2585 | struct bwi_rf *rf = &mac->mac_rf; |
| 2586 | struct bwi_tpctl tpctl; |
| 2587 | int bbp_atten, rf_atten, tp_ctrl1; |
| 2588 | |
| 2589 | bcopy(&mac->mac_tpctl, &tpctl, sizeof(tpctl)); |
| 2590 | |
| 2591 | /* NOTE: Use signed value to do calculation */ |
| 2592 | bbp_atten = tpctl.bbp_atten; |
| 2593 | rf_atten = tpctl.rf_atten; |
| 2594 | tp_ctrl1 = tpctl.tp_ctrl1; |
| 2595 | |
| 2596 | bbp_atten += bbp_atten_adj; |
| 2597 | rf_atten += rf_atten_adj; |
| 2598 | |
| 2599 | bwi_mac_balance_atten(&bbp_atten, &rf_atten); |
| 2600 | |
| 2601 | if (rf->rf_type == BWI_RF_T_BCM20500x2050 && rf->rf_rev == 2) { |
| 2602 | if (rf_atten <= 1) { |
| 2603 | if (tp_ctrl1 == 0) { |
| 2604 | tp_ctrl1 = 3; |
| 2605 | bbp_atten += 2; |
| 2606 | rf_atten += 2; |
| 2607 | } else if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9(1 << 1)) { |
| 2608 | bbp_atten += |
| 2609 | (BWI_RF_ATTEN_FACTOR4 * (rf_atten - 2)); |
| 2610 | rf_atten = 2; |
| 2611 | } |
| 2612 | } else if (rf_atten > 4 && tp_ctrl1 != 0) { |
| 2613 | tp_ctrl1 = 0; |
| 2614 | if (bbp_atten < 3) { |
| 2615 | bbp_atten += 2; |
| 2616 | rf_atten -= 3; |
| 2617 | } else { |
| 2618 | bbp_atten -= 2; |
| 2619 | rf_atten -= 2; |
| 2620 | } |
| 2621 | } |
| 2622 | bwi_mac_balance_atten(&bbp_atten, &rf_atten); |
| 2623 | } |
| 2624 | |
| 2625 | tpctl.bbp_atten = bbp_atten; |
| 2626 | tpctl.rf_atten = rf_atten; |
| 2627 | tpctl.tp_ctrl1 = tp_ctrl1; |
| 2628 | |
| 2629 | bwi_mac_lock(mac); |
| 2630 | bwi_mac_set_tpctl_11bg(mac, &tpctl); |
| 2631 | bwi_mac_unlock(mac); |
| 2632 | } |
| 2633 | |
| 2634 | /* |
| 2635 | * http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower |
| 2636 | */ |
| 2637 | void |
| 2638 | bwi_mac_calibrate_txpower(struct bwi_mac *mac, enum bwi_txpwrcb_type type) |
| 2639 | { |
| 2640 | struct bwi_softc *sc = mac->mac_sc; |
| 2641 | struct bwi_rf *rf = &mac->mac_rf; |
| 2642 | 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 | if (mac->mac_flags & BWI_MAC_F_TPCTL_ERROR0x40) { |
| 2647 | DPRINTF(1, "%s: tpctl error happened, can't set txpower\n", |
| 2648 | sc->sc_dev.dv_xname); |
| 2649 | return; |
| 2650 | } |
| 2651 | |
| 2652 | if (BWI_IS_BRCM_BU4306(sc)((sc)->sc_pci_subvid == 0x14e4 && (sc)->sc_pci_subdid == 0x416)) { |
| 2653 | DPRINTF(1, "%s: BU4306, can't set txpower\n", |
| 2654 | sc->sc_dev.dv_xname); |
| 2655 | return; |
| 2656 | } |
| 2657 | |
| 2658 | /* |
| 2659 | * Save latest TSSI and reset the related memory objects |
| 2660 | */ |
| 2661 | ofdm_tssi = 0; |
| 2662 | error = bwi_rf_get_latest_tssi(mac, tssi, BWI_COMM_MOBJ_TSSI_DS0x58); |
| 2663 | if (error) { |
| 2664 | DPRINTF(1, "%s: no DS tssi\n", sc->sc_dev.dv_xname); |
| 2665 | |
| 2666 | if (mac->mac_phy.phy_mode == IEEE80211_MODE_11B) { |
| 2667 | if (type == BWI_TXPWR_FORCE) { |
| 2668 | rf_atten_adj = 0; |
| 2669 | bbp_atten_adj = 1; |
| 2670 | goto calib; |
| 2671 | } else { |
| 2672 | return; |
| 2673 | } |
| 2674 | } |
| 2675 | |
| 2676 | error = bwi_rf_get_latest_tssi(mac, tssi, |
| 2677 | BWI_COMM_MOBJ_TSSI_OFDM0x70); |
| 2678 | if (error) { |
| 2679 | DPRINTF(1, "%s: no OFDM tssi\n", sc->sc_dev.dv_xname); |
| 2680 | if (type == BWI_TXPWR_FORCE) { |
| 2681 | rf_atten_adj = 0; |
| 2682 | bbp_atten_adj = 1; |
| 2683 | goto calib; |
| 2684 | } else { |
| 2685 | return; |
| 2686 | } |
| 2687 | } |
| 2688 | |
| 2689 | for (i = 0; i < 4; ++i) { |
| 2690 | tssi[i] += 0x20; |
| 2691 | tssi[i] &= 0x3f; |
| 2692 | } |
| 2693 | ofdm_tssi = 1; |
| 2694 | } |
| 2695 | 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 | tssi_avg = (tssi[0] + tssi[1] + tssi[2] + tssi[3] + 8) / 4; |
| 2707 | if (ofdm_tssi && (HFLAGS_READ(mac)bwi_hostflags_read((mac)) & BWI_HFLAG_PWR_BOOST_DS0x8ULL)) |
| 2708 | tssi_avg -= 13; |
| 2709 | |
| 2710 | DPRINTF(1, "%s: tssi avg %d\n", sc->sc_dev.dv_xname, tssi_avg); |
| 2711 | |
| 2712 | error = bwi_rf_tssi2dbm(mac, tssi_avg, &cur_txpwr); |
| 2713 | if (error) |
| 2714 | return; |
| 2715 | DPRINTF(1, "%s: current txpower %d\n", sc->sc_dev.dv_xname, cur_txpwr); |
| 2716 | |
| 2717 | txpwr_diff = rf->rf_txpower_max - cur_txpwr; /* XXX ni_txpower */ |
| 2718 | |
| 2719 | rf_atten_adj = -howmany(txpwr_diff, 8)(((txpwr_diff) + ((8) - 1)) / (8)); |
| 2720 | |
| 2721 | if (type == BWI_TXPWR_INIT) { |
| 2722 | /* |
| 2723 | * Move toward EEPROM max TX power as fast as we can |
| 2724 | */ |
| 2725 | bbp_atten_adj = -txpwr_diff; |
| 2726 | } else { |
| 2727 | bbp_atten_adj = -(txpwr_diff / 2); |
| 2728 | } |
| 2729 | bbp_atten_adj -= (BWI_RF_ATTEN_FACTOR4 * rf_atten_adj); |
| 2730 | |
| 2731 | 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 | 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 | bwi_mac_adjust_tpctl(mac, rf_atten_adj, bbp_atten_adj); |
| 2742 | /* TODO: LO */ |
| 2743 | } |
| 2744 | |
| 2745 | void |
| 2746 | bwi_mac_lock(struct bwi_mac *mac) |
| 2747 | { |
| 2748 | struct bwi_softc *sc = mac->mac_sc; |
| 2749 | |
| 2750 | KASSERT((mac->mac_flags & BWI_MAC_F_LOCKED) == 0)(((mac->mac_flags & 0x20) == 0) ? (void)0 : __assert("diagnostic " , "/usr/src/sys/dev/ic/bwi.c", 2750, "(mac->mac_flags & BWI_MAC_F_LOCKED) == 0" )); |
| 2751 | |
| 2752 | if (mac->mac_revmac_regwin.rw_rev < 3) |
| 2753 | bwi_mac_stop(mac); |
| 2754 | else |
| 2755 | #ifndef IEEE80211_STA_ONLY |
| 2756 | if (sc->sc_ic.ic_opmode != IEEE80211_M_HOSTAP) |
| 2757 | #endif |
| 2758 | bwi_mac_config_ps(mac); |
| 2759 | |
| 2760 | CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_RFLOCK)((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x00000120))), ((((((sc))->sc_mem_bt)->read_4((((sc)) ->sc_mem_bh), (((0x00000120))))) | ((1U << 19)))))); |
| 2761 | |
| 2762 | /* Flush pending bus write */ |
| 2763 | CSR_READ_4(sc, BWI_MAC_STATUS)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000120 )))); |
| 2764 | DELAY(10)(*delay_func)(10); |
| 2765 | |
| 2766 | mac->mac_flags |= BWI_MAC_F_LOCKED0x20; |
| 2767 | } |
| 2768 | |
| 2769 | void |
| 2770 | bwi_mac_unlock(struct bwi_mac *mac) |
| 2771 | { |
| 2772 | struct bwi_softc *sc = mac->mac_sc; |
| 2773 | |
| 2774 | KASSERT(mac->mac_flags & BWI_MAC_F_LOCKED)((mac->mac_flags & 0x20) ? (void)0 : __assert("diagnostic " , "/usr/src/sys/dev/ic/bwi.c", 2774, "mac->mac_flags & BWI_MAC_F_LOCKED" )); |
| 2775 | |
| 2776 | CSR_READ_2(sc, BWI_PHYINFO)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x03e0 )))); /* dummy read */ |
| 2777 | |
| 2778 | CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_RFLOCK)((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x00000120))), ((((((sc))->sc_mem_bt)->read_4((((sc)) ->sc_mem_bh), (((0x00000120))))) & ~((1U << 19)) )))); |
| 2779 | |
| 2780 | if (mac->mac_revmac_regwin.rw_rev < 3) |
| 2781 | bwi_mac_start(mac); |
| 2782 | else |
| 2783 | #ifndef IEEE80211_STA_ONLY |
| 2784 | if (sc->sc_ic.ic_opmode != IEEE80211_M_HOSTAP) |
| 2785 | #endif |
| 2786 | bwi_mac_config_ps(mac); |
| 2787 | |
| 2788 | mac->mac_flags &= ~BWI_MAC_F_LOCKED0x20; |
| 2789 | } |
| 2790 | |
| 2791 | void |
| 2792 | bwi_mac_set_promisc(struct bwi_mac *mac, int promisc) |
| 2793 | { |
| 2794 | struct bwi_softc *sc = mac->mac_sc; |
| 2795 | |
| 2796 | if (mac->mac_revmac_regwin.rw_rev < 5) /* Promisc is always on */ |
| 2797 | return; |
| 2798 | |
| 2799 | if (promisc) |
| 2800 | CSR_SETBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PROMISC)((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x00000120))), ((((((sc))->sc_mem_bt)->read_4((((sc)) ->sc_mem_bh), (((0x00000120))))) | ((1U << 24)))))); |
| 2801 | else |
| 2802 | CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PROMISC)((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x00000120))), ((((((sc))->sc_mem_bt)->read_4((((sc)) ->sc_mem_bh), (((0x00000120))))) & ~((1U << 24)) )))); |
| 2803 | } |
| 2804 | |
| 2805 | /* PHY */ |
| 2806 | |
| 2807 | void |
| 2808 | bwi_phy_write(struct bwi_mac *mac, uint16_t ctrl, uint16_t data) |
| 2809 | { |
| 2810 | struct bwi_softc *sc = mac->mac_sc; |
| 2811 | |
| 2812 | /* TODO: 11A */ |
| 2813 | CSR_WRITE_2(sc, BWI_PHY_CTRL, ctrl)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03fc )), ((ctrl)))); |
| 2814 | CSR_WRITE_2(sc, BWI_PHY_DATA, data)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03fe )), ((data)))); |
| 2815 | } |
| 2816 | |
| 2817 | uint16_t |
| 2818 | bwi_phy_read(struct bwi_mac *mac, uint16_t ctrl) |
| 2819 | { |
| 2820 | struct bwi_softc *sc = mac->mac_sc; |
| 2821 | |
| 2822 | /* TODO: 11A */ |
| 2823 | CSR_WRITE_2(sc, BWI_PHY_CTRL, ctrl)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03fc )), ((ctrl)))); |
| 2824 | return (CSR_READ_2(sc, BWI_PHY_DATA)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x03fe ))))); |
| 2825 | } |
| 2826 | |
| 2827 | int |
| 2828 | bwi_phy_attach(struct bwi_mac *mac) |
| 2829 | { |
| 2830 | struct bwi_softc *sc = mac->mac_sc; |
| 2831 | 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 | val = CSR_READ_2(sc, BWI_PHYINFO)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x03e0 )))); |
| 2838 | phyrev = __SHIFTOUT(val, BWI_PHYINFO_REV_MASK)(((val) & (0x000f)) / ((((0x000f) - 1) & (0x000f)) ^ ( 0x000f))); |
| 2839 | phytype = __SHIFTOUT(val, BWI_PHYINFO_TYPE_MASK)(((val) & (0x0f00)) / ((((0x0f00) - 1) & (0x0f00)) ^ ( 0x0f00))); |
| 2840 | phyver = __SHIFTOUT(val, BWI_PHYINFO_VER_MASK)(((val) & (0xf000)) / ((((0xf000) - 1) & (0xf000)) ^ ( 0xf000))); |
| 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 | switch (phytype) { |
| 2849 | case BWI_PHYINFO_TYPE_11A0: |
| 2850 | if (phyrev >= 4) { |
| 2851 | printf("%s: unsupported 11A PHY, rev %u\n", |
| 2852 | sc->sc_dev.dv_xname, phyrev); |
| 2853 | return (ENXIO6); |
| 2854 | } |
| 2855 | phy->phy_init = bwi_phy_init_11a; |
| 2856 | phy->phy_mode = IEEE80211_MODE_11A; |
| 2857 | phy->phy_tbl_ctrl = BWI_PHYR_TBL_CTRL_11A0x072; |
| 2858 | phy->phy_tbl_data_lo = BWI_PHYR_TBL_DATA_LO_11A0x073; |
| 2859 | phy->phy_tbl_data_hi = BWI_PHYR_TBL_DATA_HI_11A0x074; |
| 2860 | break; |
| 2861 | case BWI_PHYINFO_TYPE_11B1: |
| 2862 | for (i = 0; i < nitems(bwi_sup_bphy)(sizeof((bwi_sup_bphy)) / sizeof((bwi_sup_bphy)[0])); ++i) { |
| 2863 | if (phyrev == bwi_sup_bphy[i].rev) { |
| 2864 | phy->phy_init = bwi_sup_bphy[i].init; |
| 2865 | break; |
| 2866 | } |
| 2867 | } |
| 2868 | if (i == nitems(bwi_sup_bphy)(sizeof((bwi_sup_bphy)) / sizeof((bwi_sup_bphy)[0]))) { |
| 2869 | printf("%s: unsupported 11B PHY, rev %u\n", |
| 2870 | sc->sc_dev.dv_xname, phyrev); |
| 2871 | return (ENXIO6); |
| 2872 | } |
| 2873 | phy->phy_mode = IEEE80211_MODE_11B; |
| 2874 | break; |
| 2875 | case BWI_PHYINFO_TYPE_11G2: |
| 2876 | if (phyrev > 8) { |
| 2877 | printf("%s: unsupported 11G PHY, rev %u\n", |
| 2878 | sc->sc_dev.dv_xname, phyrev); |
| 2879 | return (ENXIO6); |
| 2880 | } |
| 2881 | phy->phy_init = bwi_phy_init_11g; |
| 2882 | phy->phy_mode = IEEE80211_MODE_11G; |
| 2883 | phy->phy_tbl_ctrl = BWI_PHYR_TBL_CTRL_11G0x472; |
| 2884 | phy->phy_tbl_data_lo = BWI_PHYR_TBL_DATA_LO_11G0x473; |
| 2885 | phy->phy_tbl_data_hi = BWI_PHYR_TBL_DATA_HI_11G0x474; |
| 2886 | break; |
| 2887 | default: |
| 2888 | printf("%s: unsupported PHY type %d\n", |
| 2889 | sc->sc_dev.dv_xname, phytype); |
| 2890 | return (ENXIO6); |
| 2891 | } |
| 2892 | phy->phy_rev = phyrev; |
| 2893 | phy->phy_version = phyver; |
| 2894 | |
| 2895 | return (0); |
| 2896 | } |
| 2897 | |
| 2898 | void |
| 2899 | bwi_phy_set_bbp_atten(struct bwi_mac *mac, uint16_t bbp_atten) |
| 2900 | { |
| 2901 | struct bwi_phy *phy = &mac->mac_phy; |
| 2902 | uint16_t mask = 0x000f; |
| 2903 | |
| 2904 | if (phy->phy_version == 0) { |
| 2905 | CSR_FILT_SETBITS_2(mac->mac_sc, BWI_BBP_ATTEN, ~mask,((((mac->mac_sc))->sc_mem_bt)->write_2((((mac->mac_sc ))->sc_mem_bh), (((0x03e6))), (((((((mac->mac_sc))-> sc_mem_bt)->read_2((((mac->mac_sc))->sc_mem_bh), ((( 0x03e6))))) & (~mask)) | (((bbp_atten) * ((((mask) - 1) & (mask)) ^ (mask)))))))) |
| 2906 | __SHIFTIN(bbp_atten, mask))((((mac->mac_sc))->sc_mem_bt)->write_2((((mac->mac_sc ))->sc_mem_bh), (((0x03e6))), (((((((mac->mac_sc))-> sc_mem_bt)->read_2((((mac->mac_sc))->sc_mem_bh), ((( 0x03e6))))) & (~mask)) | (((bbp_atten) * ((((mask) - 1) & (mask)) ^ (mask)))))))); |
| 2907 | } else { |
| 2908 | if (phy->phy_version > 1) |
| 2909 | mask <<= 2; |
| 2910 | else |
| 2911 | mask <<= 3; |
| 2912 | PHY_FILT_SETBITS(mac, BWI_PHYR_BBP_ATTEN, ~mask,bwi_phy_write(((mac)), ((0x060)), ((bwi_phy_read(((mac)), ((0x060 ))) & (~mask)) | (((bbp_atten) * ((((mask) - 1) & (mask )) ^ (mask)))))) |
| 2913 | __SHIFTIN(bbp_atten, mask))bwi_phy_write(((mac)), ((0x060)), ((bwi_phy_read(((mac)), ((0x060 ))) & (~mask)) | (((bbp_atten) * ((((mask) - 1) & (mask )) ^ (mask)))))); |
| 2914 | } |
| 2915 | } |
| 2916 | |
| 2917 | int |
| 2918 | bwi_phy_calibrate(struct bwi_mac *mac) |
| 2919 | { |
| 2920 | struct bwi_phy *phy = &mac->mac_phy; |
| 2921 | |
| 2922 | /* Dummy read */ |
| 2923 | CSR_READ_4(mac->mac_sc, BWI_MAC_STATUS)(((mac->mac_sc)->sc_mem_bt)->read_4(((mac->mac_sc )->sc_mem_bh), ((0x00000120)))); |
| 2924 | |
| 2925 | /* Don't re-init */ |
| 2926 | if (phy->phy_flags & BWI_PHY_F_CALIBRATED0x1) |
| 2927 | return (0); |
| 2928 | |
| 2929 | if (phy->phy_mode == IEEE80211_MODE_11G && phy->phy_rev == 1) { |
| 2930 | bwi_mac_reset(mac, 0); |
| 2931 | bwi_phy_init_11g(mac); |
| 2932 | bwi_mac_reset(mac, 1); |
| 2933 | } |
| 2934 | |
| 2935 | phy->phy_flags |= BWI_PHY_F_CALIBRATED0x1; |
| 2936 | |
| 2937 | return (0); |
| 2938 | } |
| 2939 | |
| 2940 | void |
| 2941 | bwi_tbl_write_2(struct bwi_mac *mac, uint16_t ofs, uint16_t data) |
| 2942 | { |
| 2943 | struct bwi_phy *phy = &mac->mac_phy; |
| 2944 | |
| 2945 | KASSERT(phy->phy_tbl_ctrl != 0 && phy->phy_tbl_data_lo != 0)((phy->phy_tbl_ctrl != 0 && phy->phy_tbl_data_lo != 0) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c" , 2945, "phy->phy_tbl_ctrl != 0 && phy->phy_tbl_data_lo != 0" )); |
| 2946 | PHY_WRITE(mac, phy->phy_tbl_ctrl, ofs)bwi_phy_write((mac), (phy->phy_tbl_ctrl), (ofs)); |
| 2947 | PHY_WRITE(mac, phy->phy_tbl_data_lo, data)bwi_phy_write((mac), (phy->phy_tbl_data_lo), (data)); |
| 2948 | } |
| 2949 | |
| 2950 | void |
| 2951 | bwi_tbl_write_4(struct bwi_mac *mac, uint16_t ofs, uint32_t data) |
| 2952 | { |
| 2953 | struct bwi_phy *phy = &mac->mac_phy; |
| 2954 | |
| 2955 | KASSERT(phy->phy_tbl_data_lo != 0 && phy->phy_tbl_data_hi != 0 &&((phy->phy_tbl_data_lo != 0 && phy->phy_tbl_data_hi != 0 && phy->phy_tbl_ctrl != 0) ? (void)0 : __assert ("diagnostic ", "/usr/src/sys/dev/ic/bwi.c", 2956, "phy->phy_tbl_data_lo != 0 && phy->phy_tbl_data_hi != 0 && phy->phy_tbl_ctrl != 0" )) |
| 2956 | phy->phy_tbl_ctrl != 0)((phy->phy_tbl_data_lo != 0 && phy->phy_tbl_data_hi != 0 && phy->phy_tbl_ctrl != 0) ? (void)0 : __assert ("diagnostic ", "/usr/src/sys/dev/ic/bwi.c", 2956, "phy->phy_tbl_data_lo != 0 && phy->phy_tbl_data_hi != 0 && phy->phy_tbl_ctrl != 0" )); |
| 2957 | |
| 2958 | PHY_WRITE(mac, phy->phy_tbl_ctrl, ofs)bwi_phy_write((mac), (phy->phy_tbl_ctrl), (ofs)); |
| 2959 | PHY_WRITE(mac, phy->phy_tbl_data_hi, data >> 16)bwi_phy_write((mac), (phy->phy_tbl_data_hi), (data >> 16)); |
| 2960 | PHY_WRITE(mac, phy->phy_tbl_data_lo, data & 0xffff)bwi_phy_write((mac), (phy->phy_tbl_data_lo), (data & 0xffff )); |
| 2961 | } |
| 2962 | |
| 2963 | void |
| 2964 | bwi_nrssi_write(struct bwi_mac *mac, uint16_t ofs, int16_t data) |
| 2965 | { |
| 2966 | PHY_WRITE(mac, BWI_PHYR_NRSSI_CTRL, ofs)bwi_phy_write((mac), (0x803), (ofs)); |
| 2967 | PHY_WRITE(mac, BWI_PHYR_NRSSI_DATA, (uint16_t)data)bwi_phy_write((mac), (0x804), ((uint16_t)data)); |
| 2968 | } |
| 2969 | |
| 2970 | int16_t |
| 2971 | bwi_nrssi_read(struct bwi_mac *mac, uint16_t ofs) |
| 2972 | { |
| 2973 | PHY_WRITE(mac, BWI_PHYR_NRSSI_CTRL, ofs)bwi_phy_write((mac), (0x803), (ofs)); |
| 2974 | return ((int16_t)PHY_READ(mac, BWI_PHYR_NRSSI_DATA)bwi_phy_read((mac), (0x804))); |
| 2975 | } |
| 2976 | |
| 2977 | void |
| 2978 | bwi_phy_init_11a(struct bwi_mac *mac) |
| 2979 | { |
| 2980 | /* TODO: 11A */ |
| 2981 | } |
| 2982 | |
| 2983 | void |
| 2984 | bwi_phy_init_11g(struct bwi_mac *mac) |
| 2985 | { |
| 2986 | struct bwi_softc *sc = mac->mac_sc; |
| 2987 | struct bwi_phy *phy = &mac->mac_phy; |
| 2988 | struct bwi_rf *rf = &mac->mac_rf; |
| 2989 | const struct bwi_tpctl *tpctl = &mac->mac_tpctl; |
| 2990 | |
| 2991 | if (phy->phy_rev == 1) |
| 2992 | bwi_phy_init_11b_rev5(mac); |
| 2993 | else |
| 2994 | bwi_phy_init_11b_rev6(mac); |
| 2995 | |
| 2996 | if (phy->phy_rev >= 2 || (phy->phy_flags & BWI_PHY_F_LINKED0x2)) |
| 2997 | bwi_phy_config_11g(mac); |
| 2998 | |
| 2999 | if (phy->phy_rev >= 2) { |
| 3000 | PHY_WRITE(mac, 0x814, 0)bwi_phy_write((mac), (0x814), (0)); |
| 3001 | PHY_WRITE(mac, 0x815, 0)bwi_phy_write((mac), (0x815), (0)); |
| 3002 | |
| 3003 | if (phy->phy_rev == 2) { |
| 3004 | PHY_WRITE(mac, 0x811, 0)bwi_phy_write((mac), (0x811), (0)); |
| 3005 | PHY_WRITE(mac, 0x15, 0xc0)bwi_phy_write((mac), (0x15), (0xc0)); |
| 3006 | } else if (phy->phy_rev > 5) { |
| 3007 | PHY_WRITE(mac, 0x811, 0x400)bwi_phy_write((mac), (0x811), (0x400)); |
| 3008 | PHY_WRITE(mac, 0x15, 0xc0)bwi_phy_write((mac), (0x15), (0xc0)); |
| 3009 | } |
| 3010 | } |
| 3011 | |
| 3012 | if (phy->phy_rev >= 2 || (phy->phy_flags & BWI_PHY_F_LINKED0x2)) { |
| 3013 | uint16_t val; |
| 3014 | |
| 3015 | val = PHY_READ(mac, 0x400)bwi_phy_read((mac), (0x400)) & 0xff; |
| 3016 | if (val == 3 || val == 5) { |
| 3017 | PHY_WRITE(mac, 0x4c2, 0x1816)bwi_phy_write((mac), (0x4c2), (0x1816)); |
| 3018 | PHY_WRITE(mac, 0x4c3, 0x8006)bwi_phy_write((mac), (0x4c3), (0x8006)); |
| 3019 | if (val == 5) { |
| 3020 | PHY_FILT_SETBITS(mac, 0x4cc,bwi_phy_write(((mac)), ((0x4cc)), ((bwi_phy_read(((mac)), ((0x4cc ))) & (0xff)) | (0x1f00))) |
| 3021 | 0xff, 0x1f00)bwi_phy_write(((mac)), ((0x4cc)), ((bwi_phy_read(((mac)), ((0x4cc ))) & (0xff)) | (0x1f00))); |
| 3022 | } |
| 3023 | } |
| 3024 | } |
| 3025 | |
| 3026 | if ((phy->phy_rev <= 2 && (phy->phy_flags & BWI_PHY_F_LINKED0x2)) || |
| 3027 | phy->phy_rev >= 2) |
| 3028 | PHY_WRITE(mac, 0x47e, 0x78)bwi_phy_write((mac), (0x47e), (0x78)); |
| 3029 | |
| 3030 | if (rf->rf_rev == 8) { |
| 3031 | PHY_SETBITS(mac, 0x801, 0x80)bwi_phy_write(((mac)), ((0x801)), (bwi_phy_read(((mac)), ((0x801 ))) | (0x80))); |
| 3032 | PHY_SETBITS(mac, 0x43e, 0x4)bwi_phy_write(((mac)), ((0x43e)), (bwi_phy_read(((mac)), ((0x43e ))) | (0x4))); |
| 3033 | } |
| 3034 | |
| 3035 | if (phy->phy_rev >= 2 && (phy->phy_flags & BWI_PHY_F_LINKED0x2)) |
| 3036 | bwi_rf_get_gains(mac); |
| 3037 | |
| 3038 | if (rf->rf_rev != 8) |
| 3039 | bwi_rf_init(mac); |
| 3040 | |
| 3041 | if (tpctl->tp_ctrl2 == 0xffff) { |
| 3042 | bwi_rf_lo_update(mac); |
| 3043 | } else { |
| 3044 | if (rf->rf_type == BWI_RF_T_BCM20500x2050 && rf->rf_rev == 8) { |
| 3045 | RF_WRITE(mac, 0x52,bwi_rf_write((mac), (0x52), ((tpctl->tp_ctrl1 << 4) | tpctl->tp_ctrl2)) |
| 3046 | (tpctl->tp_ctrl1 << 4) | tpctl->tp_ctrl2)bwi_rf_write((mac), (0x52), ((tpctl->tp_ctrl1 << 4) | tpctl->tp_ctrl2)); |
| 3047 | } else { |
| 3048 | RF_FILT_SETBITS(mac, 0x52, 0xfff0, tpctl->tp_ctrl2)bwi_rf_write(((mac)), ((0x52)), ((bwi_rf_read(((mac)), ((0x52 ))) & (0xfff0)) | (tpctl->tp_ctrl2))); |
| 3049 | } |
| 3050 | |
| 3051 | if (phy->phy_rev >= 6) { |
| 3052 | PHY_FILT_SETBITS(mac, 0x36, 0xfff,bwi_phy_write(((mac)), ((0x36)), ((bwi_phy_read(((mac)), ((0x36 ))) & (0xfff)) | (tpctl->tp_ctrl2 << 12))) |
| 3053 | tpctl->tp_ctrl2 << 12)bwi_phy_write(((mac)), ((0x36)), ((bwi_phy_read(((mac)), ((0x36 ))) & (0xfff)) | (tpctl->tp_ctrl2 << 12))); |
| 3054 | } |
| 3055 | |
| 3056 | if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9(1 << 1)) |
| 3057 | PHY_WRITE(mac, 0x2e, 0x8075)bwi_phy_write((mac), (0x2e), (0x8075)); |
| 3058 | else |
| 3059 | PHY_WRITE(mac, 0x2e, 0x807f)bwi_phy_write((mac), (0x2e), (0x807f)); |
| 3060 | |
| 3061 | if (phy->phy_rev < 2) |
| 3062 | PHY_WRITE(mac, 0x2f, 0x101)bwi_phy_write((mac), (0x2f), (0x101)); |
| 3063 | else |
| 3064 | PHY_WRITE(mac, 0x2f, 0x202)bwi_phy_write((mac), (0x2f), (0x202)); |
| 3065 | } |
| 3066 | |
| 3067 | if ((phy->phy_flags & BWI_PHY_F_LINKED0x2) || phy->phy_rev >= 2) { |
| 3068 | bwi_rf_lo_adjust(mac, tpctl); |
| 3069 | PHY_WRITE(mac, 0x80f, 0x8078)bwi_phy_write((mac), (0x80f), (0x8078)); |
| 3070 | } |
| 3071 | |
| 3072 | if ((sc->sc_card_flags & BWI_CARD_F_SW_NRSSI(1 << 3)) == 0) { |
| 3073 | bwi_rf_init_hw_nrssi_table(mac, 0xffff /* XXX */); |
| 3074 | bwi_rf_set_nrssi_thr(mac); |
| 3075 | } else if ((phy->phy_flags & BWI_PHY_F_LINKED0x2) || phy->phy_rev >= 2) { |
| 3076 | if (rf->rf_nrssi[0] == BWI_INVALID_NRSSI-1000) { |
| 3077 | KASSERT(rf->rf_nrssi[1] == BWI_INVALID_NRSSI)((rf->rf_nrssi[1] == -1000) ? (void)0 : __assert("diagnostic " , "/usr/src/sys/dev/ic/bwi.c", 3077, "rf->rf_nrssi[1] == BWI_INVALID_NRSSI" )); |
| 3078 | bwi_rf_calc_nrssi_slope(mac); |
| 3079 | } else { |
| 3080 | KASSERT(rf->rf_nrssi[1] != BWI_INVALID_NRSSI)((rf->rf_nrssi[1] != -1000) ? (void)0 : __assert("diagnostic " , "/usr/src/sys/dev/ic/bwi.c", 3080, "rf->rf_nrssi[1] != BWI_INVALID_NRSSI" )); |
| 3081 | bwi_rf_set_nrssi_thr(mac); |
| 3082 | } |
| 3083 | } |
| 3084 | |
| 3085 | if (rf->rf_rev == 8) |
| 3086 | PHY_WRITE(mac, 0x805, 0x3230)bwi_phy_write((mac), (0x805), (0x3230)); |
| 3087 | |
| 3088 | bwi_mac_init_tpctl_11bg(mac); |
| 3089 | |
| 3090 | if (sc->sc_bbp_id == BWI_BBPID_BCM43060x4306 && sc->sc_bbp_pkg == 2) { |
| 3091 | PHY_CLRBITS(mac, 0x429, 0x4000)bwi_phy_write(((mac)), ((0x429)), (bwi_phy_read(((mac)), ((0x429 ))) & ~(0x4000))); |
| 3092 | PHY_CLRBITS(mac, 0x4c3, 0x8000)bwi_phy_write(((mac)), ((0x4c3)), (bwi_phy_read(((mac)), ((0x4c3 ))) & ~(0x8000))); |
| 3093 | } |
| 3094 | } |
| 3095 | |
| 3096 | void |
| 3097 | bwi_phy_init_11b_rev2(struct bwi_mac *mac) |
| 3098 | { |
| 3099 | struct bwi_softc *sc; |
| 3100 | |
| 3101 | sc = mac->mac_sc; |
| 3102 | |
| 3103 | /* TODO: 11B */ |
| 3104 | printf("%s: %s is not implemented yet\n", |
| 3105 | sc->sc_dev.dv_xname, __func__); |
| 3106 | } |
| 3107 | |
| 3108 | void |
| 3109 | bwi_phy_init_11b_rev4(struct bwi_mac *mac) |
| 3110 | { |
| 3111 | struct bwi_softc *sc = mac->mac_sc; |
| 3112 | struct bwi_rf *rf = &mac->mac_rf; |
| 3113 | uint16_t val, ofs; |
| 3114 | u_int chan; |
| 3115 | |
| 3116 | CSR_WRITE_2(sc, BWI_BPHY_CTRL, BWI_BPHY_CTRL_INIT)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03ec )), ((0x3f22)))); |
| 3117 | |
| 3118 | PHY_WRITE(mac, 0x20, 0x301c)bwi_phy_write((mac), (0x20), (0x301c)); |
| 3119 | PHY_WRITE(mac, 0x26, 0)bwi_phy_write((mac), (0x26), (0)); |
| 3120 | PHY_WRITE(mac, 0x30, 0xc6)bwi_phy_write((mac), (0x30), (0xc6)); |
| 3121 | PHY_WRITE(mac, 0x88, 0x3e00)bwi_phy_write((mac), (0x88), (0x3e00)); |
| 3122 | |
| 3123 | for (ofs = 0, val = 0x3c3d; ofs < 30; ++ofs, val -= 0x202) |
| 3124 | PHY_WRITE(mac, 0x89 + ofs, val)bwi_phy_write((mac), (0x89 + ofs), (val)); |
| 3125 | |
| 3126 | CSR_WRITE_2(sc, BWI_PHY_MAGIC_REG1, BWI_PHY_MAGIC_REG1_VAL1)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03e4 )), ((0x3000)))); |
| 3127 | |
| 3128 | chan = rf->rf_curchan; |
| 3129 | if (chan == IEEE80211_CHAN_ANY0xffff) |
| 3130 | chan = 6; /* Force to channel 6 */ |
| 3131 | bwi_rf_set_chan(mac, chan, 0); |
| 3132 | |
| 3133 | if (rf->rf_type != BWI_RF_T_BCM20500x2050) { |
| 3134 | RF_WRITE(mac, 0x75, 0x80)bwi_rf_write((mac), (0x75), (0x80)); |
| 3135 | RF_WRITE(mac, 0x79, 0x81)bwi_rf_write((mac), (0x79), (0x81)); |
| 3136 | } |
| 3137 | |
| 3138 | RF_WRITE(mac, 0x50, 0x20)bwi_rf_write((mac), (0x50), (0x20)); |
| 3139 | RF_WRITE(mac, 0x50, 0x23)bwi_rf_write((mac), (0x50), (0x23)); |
| 3140 | |
| 3141 | if (rf->rf_type == BWI_RF_T_BCM20500x2050) { |
| 3142 | RF_WRITE(mac, 0x50, 0x20)bwi_rf_write((mac), (0x50), (0x20)); |
| 3143 | RF_WRITE(mac, 0x5a, 0x70)bwi_rf_write((mac), (0x5a), (0x70)); |
| 3144 | RF_WRITE(mac, 0x5b, 0x7b)bwi_rf_write((mac), (0x5b), (0x7b)); |
| 3145 | RF_WRITE(mac, 0x5c, 0xb0)bwi_rf_write((mac), (0x5c), (0xb0)); |
| 3146 | RF_WRITE(mac, 0x7a, 0xf)bwi_rf_write((mac), (0x7a), (0xf)); |
| 3147 | PHY_WRITE(mac, 0x38, 0x677)bwi_phy_write((mac), (0x38), (0x677)); |
| 3148 | bwi_rf_init_bcm2050(mac); |
| 3149 | } |
| 3150 | |
| 3151 | PHY_WRITE(mac, 0x14, 0x80)bwi_phy_write((mac), (0x14), (0x80)); |
| 3152 | PHY_WRITE(mac, 0x32, 0xca)bwi_phy_write((mac), (0x32), (0xca)); |
| 3153 | if (rf->rf_type == BWI_RF_T_BCM20500x2050) |
| 3154 | PHY_WRITE(mac, 0x32, 0xe0)bwi_phy_write((mac), (0x32), (0xe0)); |
| 3155 | PHY_WRITE(mac, 0x35, 0x7c2)bwi_phy_write((mac), (0x35), (0x7c2)); |
| 3156 | |
| 3157 | bwi_rf_lo_update(mac); |
| 3158 | |
| 3159 | PHY_WRITE(mac, 0x26, 0xcc00)bwi_phy_write((mac), (0x26), (0xcc00)); |
| 3160 | if (rf->rf_type == BWI_RF_T_BCM20500x2050) |
| 3161 | PHY_WRITE(mac, 0x26, 0xce00)bwi_phy_write((mac), (0x26), (0xce00)); |
| 3162 | |
| 3163 | CSR_WRITE_2(sc, BWI_RF_CHAN_EX, 0x1100)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03f4 )), ((0x1100)))); |
| 3164 | |
| 3165 | PHY_WRITE(mac, 0x2a, 0x88a3)bwi_phy_write((mac), (0x2a), (0x88a3)); |
| 3166 | if (rf->rf_type == BWI_RF_T_BCM20500x2050) |
| 3167 | PHY_WRITE(mac, 0x2a, 0x88c2)bwi_phy_write((mac), (0x2a), (0x88c2)); |
| 3168 | |
| 3169 | bwi_mac_set_tpctl_11bg(mac, NULL((void *)0)); |
| 3170 | if (sc->sc_card_flags & BWI_CARD_F_SW_NRSSI(1 << 3)) { |
| 3171 | bwi_rf_calc_nrssi_slope(mac); |
| 3172 | bwi_rf_set_nrssi_thr(mac); |
| 3173 | } |
| 3174 | bwi_mac_init_tpctl_11bg(mac); |
| 3175 | } |
| 3176 | |
| 3177 | void |
| 3178 | bwi_phy_init_11b_rev5(struct bwi_mac *mac) |
| 3179 | { |
| 3180 | struct bwi_softc *sc = mac->mac_sc; |
| 3181 | struct bwi_rf *rf = &mac->mac_rf; |
| 3182 | struct bwi_phy *phy = &mac->mac_phy; |
| 3183 | uint orig_chan; |
| 3184 | |
| 3185 | if (phy->phy_version == 1) |
| 3186 | RF_SETBITS(mac, 0x7a, 0x50)bwi_rf_write(((mac)), ((0x7a)), (bwi_rf_read(((mac)), ((0x7a) )) | (0x50))); |
| 3187 | |
| 3188 | if (sc->sc_pci_subvid != PCI_VENDOR_BROADCOM0x14e4 && |
| 3189 | sc->sc_pci_subdid != BWI_PCI_SUBDEVICE_BU43060x416) { |
| 3190 | uint16_t ofs, val; |
| 3191 | |
| 3192 | val = 0x2120; |
| 3193 | for (ofs = 0xa8; ofs < 0xc7; ++ofs) { |
| 3194 | PHY_WRITE(mac, ofs, val)bwi_phy_write((mac), (ofs), (val)); |
| 3195 | val += 0x202; |
| 3196 | } |
| 3197 | } |
| 3198 | |
| 3199 | PHY_FILT_SETBITS(mac, 0x35, 0xf0ff, 0x700)bwi_phy_write(((mac)), ((0x35)), ((bwi_phy_read(((mac)), ((0x35 ))) & (0xf0ff)) | (0x700))); |
| 3200 | |
| 3201 | if (rf->rf_type == BWI_RF_T_BCM20500x2050) |
| 3202 | PHY_WRITE(mac, 0x38, 0x667)bwi_phy_write((mac), (0x38), (0x667)); |
| 3203 | |
| 3204 | if ((phy->phy_flags & BWI_PHY_F_LINKED0x2) || phy->phy_rev >= 2) { |
| 3205 | if (rf->rf_type == BWI_RF_T_BCM20500x2050) { |
| 3206 | RF_SETBITS(mac, 0x7a, 0x20)bwi_rf_write(((mac)), ((0x7a)), (bwi_rf_read(((mac)), ((0x7a) )) | (0x20))); |
| 3207 | RF_SETBITS(mac, 0x51, 0x4)bwi_rf_write(((mac)), ((0x51)), (bwi_rf_read(((mac)), ((0x51) )) | (0x4))); |
| 3208 | } |
| 3209 | |
| 3210 | CSR_WRITE_2(sc, BWI_RF_ANTDIV, 0)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03e2 )), ((0)))); |
| 3211 | |
| 3212 | PHY_SETBITS(mac, 0x802, 0x100)bwi_phy_write(((mac)), ((0x802)), (bwi_phy_read(((mac)), ((0x802 ))) | (0x100))); |
| 3213 | PHY_SETBITS(mac, 0x42b, 0x2000)bwi_phy_write(((mac)), ((0x42b)), (bwi_phy_read(((mac)), ((0x42b ))) | (0x2000))); |
| 3214 | PHY_WRITE(mac, 0x1c, 0x186a)bwi_phy_write((mac), (0x1c), (0x186a)); |
| 3215 | |
| 3216 | PHY_FILT_SETBITS(mac, 0x13, 0xff, 0x1900)bwi_phy_write(((mac)), ((0x13)), ((bwi_phy_read(((mac)), ((0x13 ))) & (0xff)) | (0x1900))); |
| 3217 | PHY_FILT_SETBITS(mac, 0x35, 0xffc0, 0x64)bwi_phy_write(((mac)), ((0x35)), ((bwi_phy_read(((mac)), ((0x35 ))) & (0xffc0)) | (0x64))); |
| 3218 | PHY_FILT_SETBITS(mac, 0x5d, 0xff80, 0xa)bwi_phy_write(((mac)), ((0x5d)), ((bwi_phy_read(((mac)), ((0x5d ))) & (0xff80)) | (0xa))); |
| 3219 | } |
| 3220 | |
| 3221 | /* TODO: bad_frame_preempt? */ |
| 3222 | |
| 3223 | if (phy->phy_version == 1) { |
| 3224 | PHY_WRITE(mac, 0x26, 0xce00)bwi_phy_write((mac), (0x26), (0xce00)); |
| 3225 | PHY_WRITE(mac, 0x21, 0x3763)bwi_phy_write((mac), (0x21), (0x3763)); |
| 3226 | PHY_WRITE(mac, 0x22, 0x1bc3)bwi_phy_write((mac), (0x22), (0x1bc3)); |
| 3227 | PHY_WRITE(mac, 0x23, 0x6f9)bwi_phy_write((mac), (0x23), (0x6f9)); |
| 3228 | PHY_WRITE(mac, 0x24, 0x37e)bwi_phy_write((mac), (0x24), (0x37e)); |
| 3229 | } else |
| 3230 | PHY_WRITE(mac, 0x26, 0xcc00)bwi_phy_write((mac), (0x26), (0xcc00)); |
| 3231 | PHY_WRITE(mac, 0x30, 0xc6)bwi_phy_write((mac), (0x30), (0xc6)); |
| 3232 | |
| 3233 | CSR_WRITE_2(sc, BWI_BPHY_CTRL, BWI_BPHY_CTRL_INIT)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03ec )), ((0x3f22)))); |
| 3234 | |
| 3235 | if (phy->phy_version == 1) |
| 3236 | PHY_WRITE(mac, 0x20, 0x3e1c)bwi_phy_write((mac), (0x20), (0x3e1c)); |
| 3237 | else |
| 3238 | PHY_WRITE(mac, 0x20, 0x301c)bwi_phy_write((mac), (0x20), (0x301c)); |
| 3239 | |
| 3240 | if (phy->phy_version == 0) |
| 3241 | CSR_WRITE_2(sc, BWI_PHY_MAGIC_REG1, BWI_PHY_MAGIC_REG1_VAL1)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03e4 )), ((0x3000)))); |
| 3242 | |
| 3243 | /* Force to channel 7 */ |
| 3244 | orig_chan = rf->rf_curchan; |
| 3245 | bwi_rf_set_chan(mac, 7, 0); |
| 3246 | |
| 3247 | if (rf->rf_type != BWI_RF_T_BCM20500x2050) { |
| 3248 | RF_WRITE(mac, 0x75, 0x80)bwi_rf_write((mac), (0x75), (0x80)); |
| 3249 | RF_WRITE(mac, 0x79, 0x81)bwi_rf_write((mac), (0x79), (0x81)); |
| 3250 | } |
| 3251 | |
| 3252 | RF_WRITE(mac, 0x50, 0x20)bwi_rf_write((mac), (0x50), (0x20)); |
| 3253 | RF_WRITE(mac, 0x50, 0x23)bwi_rf_write((mac), (0x50), (0x23)); |
| 3254 | |
| 3255 | if (rf->rf_type == BWI_RF_T_BCM20500x2050) { |
| 3256 | RF_WRITE(mac, 0x50, 0x20)bwi_rf_write((mac), (0x50), (0x20)); |
| 3257 | RF_WRITE(mac, 0x5a, 0x70)bwi_rf_write((mac), (0x5a), (0x70)); |
| 3258 | } |
| 3259 | |
| 3260 | RF_WRITE(mac, 0x5b, 0x7b)bwi_rf_write((mac), (0x5b), (0x7b)); |
| 3261 | RF_WRITE(mac, 0x5c, 0xb0)bwi_rf_write((mac), (0x5c), (0xb0)); |
| 3262 | RF_SETBITS(mac, 0x7a, 0x7)bwi_rf_write(((mac)), ((0x7a)), (bwi_rf_read(((mac)), ((0x7a) )) | (0x7))); |
| 3263 | |
| 3264 | bwi_rf_set_chan(mac, orig_chan, 0); |
| 3265 | |
| 3266 | PHY_WRITE(mac, 0x14, 0x80)bwi_phy_write((mac), (0x14), (0x80)); |
| 3267 | PHY_WRITE(mac, 0x32, 0xca)bwi_phy_write((mac), (0x32), (0xca)); |
| 3268 | PHY_WRITE(mac, 0x2a, 0x88a3)bwi_phy_write((mac), (0x2a), (0x88a3)); |
| 3269 | |
| 3270 | bwi_mac_set_tpctl_11bg(mac, NULL((void *)0)); |
| 3271 | |
| 3272 | if (rf->rf_type == BWI_RF_T_BCM20500x2050) |
| 3273 | RF_WRITE(mac, 0x5d, 0xd)bwi_rf_write((mac), (0x5d), (0xd)); |
| 3274 | |
| 3275 | CSR_FILT_SETBITS_2(sc, BWI_PHY_MAGIC_REG1, 0xffc0, 0x4)((((sc))->sc_mem_bt)->write_2((((sc))->sc_mem_bh), ( ((0x03e4))), (((((((sc))->sc_mem_bt)->read_2((((sc))-> sc_mem_bh), (((0x03e4))))) & (0xffc0)) | (0x4))))); |
| 3276 | } |
| 3277 | |
| 3278 | void |
| 3279 | bwi_phy_init_11b_rev6(struct bwi_mac *mac) |
| 3280 | { |
| 3281 | struct bwi_softc *sc = mac->mac_sc; |
| 3282 | struct bwi_rf *rf = &mac->mac_rf; |
| 3283 | struct bwi_phy *phy = &mac->mac_phy; |
| 3284 | uint16_t val, ofs; |
| 3285 | uint orig_chan; |
| 3286 | |
| 3287 | PHY_WRITE(mac, 0x3e, 0x817a)bwi_phy_write((mac), (0x3e), (0x817a)); |
| 3288 | RF_SETBITS(mac, 0x7a, 0x58)bwi_rf_write(((mac)), ((0x7a)), (bwi_rf_read(((mac)), ((0x7a) )) | (0x58))); |
| 3289 | |
| 3290 | if (rf->rf_rev == 4 || rf->rf_rev == 5) { |
| 3291 | RF_WRITE(mac, 0x51, 0x37)bwi_rf_write((mac), (0x51), (0x37)); |
| 3292 | RF_WRITE(mac, 0x52, 0x70)bwi_rf_write((mac), (0x52), (0x70)); |
| 3293 | RF_WRITE(mac, 0x53, 0xb3)bwi_rf_write((mac), (0x53), (0xb3)); |
| 3294 | RF_WRITE(mac, 0x54, 0x9b)bwi_rf_write((mac), (0x54), (0x9b)); |
| 3295 | RF_WRITE(mac, 0x5a, 0x88)bwi_rf_write((mac), (0x5a), (0x88)); |
| 3296 | RF_WRITE(mac, 0x5b, 0x88)bwi_rf_write((mac), (0x5b), (0x88)); |
| 3297 | RF_WRITE(mac, 0x5d, 0x88)bwi_rf_write((mac), (0x5d), (0x88)); |
| 3298 | RF_WRITE(mac, 0x5e, 0x88)bwi_rf_write((mac), (0x5e), (0x88)); |
| 3299 | RF_WRITE(mac, 0x7d, 0x88)bwi_rf_write((mac), (0x7d), (0x88)); |
| 3300 | HFLAGS_SETBITS(mac, BWI_HFLAG_MAGIC1)bwi_hostflags_write(((mac)), (bwi_hostflags_read(((mac))) & ~(0x200ULL))); |
| 3301 | } else if (rf->rf_rev == 8) { |
| 3302 | RF_WRITE(mac, 0x51, 0)bwi_rf_write((mac), (0x51), (0)); |
| 3303 | RF_WRITE(mac, 0x52, 0x40)bwi_rf_write((mac), (0x52), (0x40)); |
| 3304 | RF_WRITE(mac, 0x53, 0xb7)bwi_rf_write((mac), (0x53), (0xb7)); |
| 3305 | RF_WRITE(mac, 0x54, 0x98)bwi_rf_write((mac), (0x54), (0x98)); |
| 3306 | RF_WRITE(mac, 0x5a, 0x88)bwi_rf_write((mac), (0x5a), (0x88)); |
| 3307 | RF_WRITE(mac, 0x5b, 0x6b)bwi_rf_write((mac), (0x5b), (0x6b)); |
| 3308 | RF_WRITE(mac, 0x5c, 0xf)bwi_rf_write((mac), (0x5c), (0xf)); |
| 3309 | if (sc->sc_card_flags & BWI_CARD_F_ALT_IQ(1 << 15)) { |
| 3310 | RF_WRITE(mac, 0x5d, 0xfa)bwi_rf_write((mac), (0x5d), (0xfa)); |
| 3311 | RF_WRITE(mac, 0x5e, 0xd8)bwi_rf_write((mac), (0x5e), (0xd8)); |
| 3312 | } else { |
| 3313 | RF_WRITE(mac, 0x5d, 0xf5)bwi_rf_write((mac), (0x5d), (0xf5)); |
| 3314 | RF_WRITE(mac, 0x5e, 0xb8)bwi_rf_write((mac), (0x5e), (0xb8)); |
| 3315 | } |
| 3316 | RF_WRITE(mac, 0x73, 0x3)bwi_rf_write((mac), (0x73), (0x3)); |
| 3317 | RF_WRITE(mac, 0x7d, 0xa8)bwi_rf_write((mac), (0x7d), (0xa8)); |
| 3318 | RF_WRITE(mac, 0x7c, 0x1)bwi_rf_write((mac), (0x7c), (0x1)); |
| 3319 | RF_WRITE(mac, 0x7e, 0x8)bwi_rf_write((mac), (0x7e), (0x8)); |
| 3320 | } |
| 3321 | |
| 3322 | val = 0x1e1f; |
| 3323 | for (ofs = 0x88; ofs < 0x98; ++ofs) { |
| 3324 | PHY_WRITE(mac, ofs, val)bwi_phy_write((mac), (ofs), (val)); |
| 3325 | val -= 0x202; |
| 3326 | } |
| 3327 | |
| 3328 | val = 0x3e3f; |
| 3329 | for (ofs = 0x98; ofs < 0xa8; ++ofs) { |
| 3330 | PHY_WRITE(mac, ofs, val)bwi_phy_write((mac), (ofs), (val)); |
| 3331 | val -= 0x202; |
| 3332 | } |
| 3333 | |
| 3334 | val = 0x2120; |
| 3335 | for (ofs = 0xa8; ofs < 0xc8; ++ofs) { |
| 3336 | PHY_WRITE(mac, ofs, (val & 0x3f3f))bwi_phy_write((mac), (ofs), ((val & 0x3f3f))); |
| 3337 | val += 0x202; |
| 3338 | |
| 3339 | /* XXX: delay 10 us to avoid PCI parity errors with BCM4318 */ |
| 3340 | DELAY(10)(*delay_func)(10); |
| 3341 | } |
| 3342 | |
| 3343 | if (phy->phy_mode == IEEE80211_MODE_11G) { |
| 3344 | RF_SETBITS(mac, 0x7a, 0x20)bwi_rf_write(((mac)), ((0x7a)), (bwi_rf_read(((mac)), ((0x7a) )) | (0x20))); |
| 3345 | RF_SETBITS(mac, 0x51, 0x4)bwi_rf_write(((mac)), ((0x51)), (bwi_rf_read(((mac)), ((0x51) )) | (0x4))); |
| 3346 | PHY_SETBITS(mac, 0x802, 0x100)bwi_phy_write(((mac)), ((0x802)), (bwi_phy_read(((mac)), ((0x802 ))) | (0x100))); |
| 3347 | PHY_SETBITS(mac, 0x42b, 0x2000)bwi_phy_write(((mac)), ((0x42b)), (bwi_phy_read(((mac)), ((0x42b ))) | (0x2000))); |
| 3348 | PHY_WRITE(mac, 0x5b, 0)bwi_phy_write((mac), (0x5b), (0)); |
| 3349 | PHY_WRITE(mac, 0x5c, 0)bwi_phy_write((mac), (0x5c), (0)); |
| 3350 | } |
| 3351 | |
| 3352 | /* Force to channel 7 */ |
| 3353 | orig_chan = rf->rf_curchan; |
| 3354 | if (orig_chan >= 8) |
| 3355 | bwi_rf_set_chan(mac, 1, 0); |
| 3356 | else |
| 3357 | bwi_rf_set_chan(mac, 13, 0); |
| 3358 | |
| 3359 | RF_WRITE(mac, 0x50, 0x20)bwi_rf_write((mac), (0x50), (0x20)); |
| 3360 | RF_WRITE(mac, 0x50, 0x23)bwi_rf_write((mac), (0x50), (0x23)); |
| 3361 | |
| 3362 | DELAY(40)(*delay_func)(40); |
| 3363 | |
| 3364 | if (rf->rf_rev < 6 || rf->rf_rev == 8) { |
| 3365 | RF_SETBITS(mac, 0x7c, 0x2)bwi_rf_write(((mac)), ((0x7c)), (bwi_rf_read(((mac)), ((0x7c) )) | (0x2))); |
| 3366 | RF_WRITE(mac, 0x50, 0x20)bwi_rf_write((mac), (0x50), (0x20)); |
| 3367 | } |
| 3368 | if (rf->rf_rev <= 2) { |
| 3369 | RF_WRITE(mac, 0x7c, 0x20)bwi_rf_write((mac), (0x7c), (0x20)); |
| 3370 | RF_WRITE(mac, 0x5a, 0x70)bwi_rf_write((mac), (0x5a), (0x70)); |
| 3371 | RF_WRITE(mac, 0x5b, 0x7b)bwi_rf_write((mac), (0x5b), (0x7b)); |
| 3372 | RF_WRITE(mac, 0x5c, 0xb0)bwi_rf_write((mac), (0x5c), (0xb0)); |
| 3373 | } |
| 3374 | |
| 3375 | RF_FILT_SETBITS(mac, 0x7a, 0xf8, 0x7)bwi_rf_write(((mac)), ((0x7a)), ((bwi_rf_read(((mac)), ((0x7a ))) & (0xf8)) | (0x7))); |
| 3376 | |
| 3377 | bwi_rf_set_chan(mac, orig_chan, 0); |
| 3378 | |
| 3379 | PHY_WRITE(mac, 0x14, 0x200)bwi_phy_write((mac), (0x14), (0x200)); |
| 3380 | if (rf->rf_rev >= 6) |
| 3381 | PHY_WRITE(mac, 0x2a, 0x88c2)bwi_phy_write((mac), (0x2a), (0x88c2)); |
| 3382 | else |
| 3383 | PHY_WRITE(mac, 0x2a, 0x8ac0)bwi_phy_write((mac), (0x2a), (0x8ac0)); |
| 3384 | PHY_WRITE(mac, 0x38, 0x668)bwi_phy_write((mac), (0x38), (0x668)); |
| 3385 | |
| 3386 | bwi_mac_set_tpctl_11bg(mac, NULL((void *)0)); |
| 3387 | |
| 3388 | if (rf->rf_rev <= 5) { |
| 3389 | PHY_FILT_SETBITS(mac, 0x5d, 0xff80, 0x3)bwi_phy_write(((mac)), ((0x5d)), ((bwi_phy_read(((mac)), ((0x5d ))) & (0xff80)) | (0x3))); |
| 3390 | if (rf->rf_rev <= 2) |
| 3391 | RF_WRITE(mac, 0x5d, 0xd)bwi_rf_write((mac), (0x5d), (0xd)); |
| 3392 | } |
| 3393 | |
| 3394 | if (phy->phy_version == 4) { |
| 3395 | CSR_WRITE_2(sc, BWI_PHY_MAGIC_REG1, BWI_PHY_MAGIC_REG1_VAL2)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03e4 )), ((0x0009)))); |
| 3396 | PHY_CLRBITS(mac, 0x61, 0xf000)bwi_phy_write(((mac)), ((0x61)), (bwi_phy_read(((mac)), ((0x61 ))) & ~(0xf000))); |
| 3397 | } else { |
| 3398 | PHY_FILT_SETBITS(mac, 0x2, 0xffc0, 0x4)bwi_phy_write(((mac)), ((0x2)), ((bwi_phy_read(((mac)), ((0x2 ))) & (0xffc0)) | (0x4))); |
| 3399 | } |
| 3400 | |
| 3401 | if (phy->phy_mode == IEEE80211_MODE_11B) { |
| 3402 | CSR_WRITE_2(sc, BWI_BBP_ATTEN, BWI_BBP_ATTEN_MAGIC2)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03e6 )), ((0x8140)))); |
| 3403 | PHY_WRITE(mac, 0x16, 0x410)bwi_phy_write((mac), (0x16), (0x410)); |
| 3404 | PHY_WRITE(mac, 0x17, 0x820)bwi_phy_write((mac), (0x17), (0x820)); |
| 3405 | PHY_WRITE(mac, 0x62, 0x7)bwi_phy_write((mac), (0x62), (0x7)); |
| 3406 | |
| 3407 | bwi_rf_init_bcm2050(mac); |
| 3408 | bwi_rf_lo_update(mac); |
| 3409 | if (sc->sc_card_flags & BWI_CARD_F_SW_NRSSI(1 << 3)) { |
| 3410 | bwi_rf_calc_nrssi_slope(mac); |
| 3411 | bwi_rf_set_nrssi_thr(mac); |
| 3412 | } |
| 3413 | bwi_mac_init_tpctl_11bg(mac); |
| 3414 | } else |
| 3415 | CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03e6 )), ((0)))); |
| 3416 | } |
| 3417 | |
| 3418 | void |
| 3419 | bwi_phy_config_11g(struct bwi_mac *mac) |
| 3420 | { |
| 3421 | struct bwi_softc *sc = mac->mac_sc; |
| 3422 | 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 | if (phy->phy_rev == 1) { |
| 3428 | PHY_WRITE(mac, 0x406, 0x4f19)bwi_phy_write((mac), (0x406), (0x4f19)); |
| 3429 | PHY_FILT_SETBITS(mac, 0x429, 0xfc3f, 0x340)bwi_phy_write(((mac)), ((0x429)), ((bwi_phy_read(((mac)), ((0x429 ))) & (0xfc3f)) | (0x340))); |
| 3430 | PHY_WRITE(mac, 0x42c, 0x5a)bwi_phy_write((mac), (0x42c), (0x5a)); |
| 3431 | PHY_WRITE(mac, 0x427, 0x1a)bwi_phy_write((mac), (0x427), (0x1a)); |
| 3432 | |
| 3433 | /* Fill frequency table */ |
| 3434 | for (i = 0; i < nitems(bwi_phy_freq_11g_rev1)(sizeof((bwi_phy_freq_11g_rev1)) / sizeof((bwi_phy_freq_11g_rev1 )[0])); ++i) { |
| 3435 | bwi_tbl_write_2(mac, BWI_PHYTBL_FREQ0x5800 + i, |
| 3436 | bwi_phy_freq_11g_rev1[i]); |
| 3437 | } |
| 3438 | |
| 3439 | /* Fill noise table */ |
| 3440 | for (i = 0; i < nitems(bwi_phy_noise_11g_rev1)(sizeof((bwi_phy_noise_11g_rev1)) / sizeof((bwi_phy_noise_11g_rev1 )[0])); ++i) { |
| 3441 | bwi_tbl_write_2(mac, BWI_PHYTBL_NOISE0x1800 + i, |
| 3442 | bwi_phy_noise_11g_rev1[i]); |
| 3443 | } |
| 3444 | |
| 3445 | /* Fill rotor table */ |
| 3446 | for (i = 0; i < nitems(bwi_phy_rotor_11g_rev1)(sizeof((bwi_phy_rotor_11g_rev1)) / sizeof((bwi_phy_rotor_11g_rev1 )[0])); ++i) { |
| 3447 | /* NB: data length is 4 bytes */ |
| 3448 | bwi_tbl_write_4(mac, BWI_PHYTBL_ROTOR0x2000 + i, |
| 3449 | bwi_phy_rotor_11g_rev1[i]); |
| 3450 | } |
| 3451 | } else { |
| 3452 | bwi_nrssi_write(mac, 0xba98, (int16_t)0x7654); /* XXX */ |
| 3453 | |
| 3454 | if (phy->phy_rev == 2) { |
| 3455 | PHY_WRITE(mac, 0x4c0, 0x1861)bwi_phy_write((mac), (0x4c0), (0x1861)); |
| 3456 | PHY_WRITE(mac, 0x4c1, 0x271)bwi_phy_write((mac), (0x4c1), (0x271)); |
| 3457 | } else if (phy->phy_rev > 2) { |
| 3458 | PHY_WRITE(mac, 0x4c0, 0x98)bwi_phy_write((mac), (0x4c0), (0x98)); |
| 3459 | PHY_WRITE(mac, 0x4c1, 0x70)bwi_phy_write((mac), (0x4c1), (0x70)); |
| 3460 | PHY_WRITE(mac, 0x4c9, 0x80)bwi_phy_write((mac), (0x4c9), (0x80)); |
| 3461 | } |
| 3462 | PHY_SETBITS(mac, 0x42b, 0x800)bwi_phy_write(((mac)), ((0x42b)), (bwi_phy_read(((mac)), ((0x42b ))) | (0x800))); |
| 3463 | |
| 3464 | /* Fill RSSI table */ |
| 3465 | for (i = 0; i < 64; ++i) |
| 3466 | bwi_tbl_write_2(mac, BWI_PHYTBL_RSSI0x4000 + i, i); |
| 3467 | |
| 3468 | /* Fill noise table */ |
| 3469 | for (i = 0; i < nitems(bwi_phy_noise_11g)(sizeof((bwi_phy_noise_11g)) / sizeof((bwi_phy_noise_11g)[0]) ); ++i) { |
| 3470 | bwi_tbl_write_2(mac, BWI_PHYTBL_NOISE0x1800 + i, |
| 3471 | bwi_phy_noise_11g[i]); |
| 3472 | } |
| 3473 | } |
| 3474 | |
| 3475 | /* |
| 3476 | * Fill noise scale table |
| 3477 | */ |
| 3478 | if (phy->phy_rev <= 2) { |
| 3479 | tbl = bwi_phy_noise_scale_11g_rev2; |
| 3480 | n = nitems(bwi_phy_noise_scale_11g_rev2)(sizeof((bwi_phy_noise_scale_11g_rev2)) / sizeof((bwi_phy_noise_scale_11g_rev2 )[0])); |
| 3481 | } else if (phy->phy_rev >= 7 && (PHY_READ(mac, 0x449)bwi_phy_read((mac), (0x449)) & 0x200)) { |
| 3482 | tbl = bwi_phy_noise_scale_11g_rev7; |
| 3483 | n = nitems(bwi_phy_noise_scale_11g_rev7)(sizeof((bwi_phy_noise_scale_11g_rev7)) / sizeof((bwi_phy_noise_scale_11g_rev7 )[0])); |
| 3484 | } else { |
| 3485 | tbl = bwi_phy_noise_scale_11g; |
| 3486 | n = nitems(bwi_phy_noise_scale_11g)(sizeof((bwi_phy_noise_scale_11g)) / sizeof((bwi_phy_noise_scale_11g )[0])); |
| 3487 | } |
| 3488 | for (i = 0; i < n; ++i) |
| 3489 | bwi_tbl_write_2(mac, BWI_PHYTBL_NOISE_SCALE0x1400 + i, tbl[i]); |
| 3490 | |
| 3491 | /* |
| 3492 | * Fill sigma square table |
| 3493 | */ |
| 3494 | if (phy->phy_rev == 2) { |
| 3495 | tbl = bwi_phy_sigma_sq_11g_rev2; |
| 3496 | n = nitems(bwi_phy_sigma_sq_11g_rev2)(sizeof((bwi_phy_sigma_sq_11g_rev2)) / sizeof((bwi_phy_sigma_sq_11g_rev2 )[0])); |
| 3497 | } 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)(sizeof((bwi_phy_sigma_sq_11g_rev7)) / sizeof((bwi_phy_sigma_sq_11g_rev7 )[0])); |
| 3500 | } else { |
| 3501 | tbl = NULL((void *)0); |
| 3502 | n = 0; |
| 3503 | } |
| 3504 | for (i = 0; i < n; ++i) |
| 3505 | bwi_tbl_write_2(mac, BWI_PHYTBL_SIGMA_SQ0x5000 + i, tbl[i]); |
| 3506 | |
| 3507 | if (phy->phy_rev == 1) { |
| 3508 | /* Fill delay table */ |
| 3509 | for (i = 0; i < nitems(bwi_phy_delay_11g_rev1)(sizeof((bwi_phy_delay_11g_rev1)) / sizeof((bwi_phy_delay_11g_rev1 )[0])); ++i) { |
| 3510 | bwi_tbl_write_4(mac, BWI_PHYTBL_DELAY0x2400 + i, |
| 3511 | bwi_phy_delay_11g_rev1[i]); |
| 3512 | } |
| 3513 | |
| 3514 | /* Fill WRSSI (Wide-Band RSSI) table */ |
| 3515 | for (i = 4; i < 20; ++i) |
| 3516 | bwi_tbl_write_2(mac, BWI_PHYTBL_WRSSI_REV10x5400 + i, 0x20); |
| 3517 | |
| 3518 | bwi_phy_config_agc(mac); |
| 3519 | |
| 3520 | wrd_ofs1 = 0x5001; |
| 3521 | wrd_ofs2 = 0x5002; |
| 3522 | } else { |
| 3523 | /* Fill WRSSI (Wide-Band RSSI) table */ |
| 3524 | for (i = 0; i < 0x20; ++i) |
| 3525 | bwi_tbl_write_2(mac, BWI_PHYTBL_WRSSI0x1000 + i, 0x820); |
| 3526 | |
| 3527 | bwi_phy_config_agc(mac); |
| 3528 | |
| 3529 | PHY_READ(mac, 0x400)bwi_phy_read((mac), (0x400)); /* Dummy read */ |
| 3530 | PHY_WRITE(mac, 0x403, 0x1000)bwi_phy_write((mac), (0x403), (0x1000)); |
| 3531 | bwi_tbl_write_2(mac, 0x3c02, 0xf); |
| 3532 | bwi_tbl_write_2(mac, 0x3c03, 0x14); |
| 3533 | |
| 3534 | wrd_ofs1 = 0x401; |
| 3535 | wrd_ofs2 = 0x402; |
| 3536 | } |
| 3537 | |
| 3538 | if (!(BWI_IS_BRCM_BU4306(sc)((sc)->sc_pci_subvid == 0x14e4 && (sc)->sc_pci_subdid == 0x416) && sc->sc_pci_revid == 0x17)) { |
| 3539 | bwi_tbl_write_2(mac, wrd_ofs1, 0x2); |
| 3540 | bwi_tbl_write_2(mac, wrd_ofs2, 0x1); |
| 3541 | } |
| 3542 | |
| 3543 | /* phy->phy_flags & BWI_PHY_F_LINKED ? */ |
| 3544 | if (sc->sc_card_flags & BWI_CARD_F_PA_GPIO9(1 << 1)) |
| 3545 | PHY_WRITE(mac, 0x46e, 0x3cf)bwi_phy_write((mac), (0x46e), (0x3cf)); |
| 3546 | } |
| 3547 | #undef N |
| 3548 | |
| 3549 | /* |
| 3550 | * Configure Automatic Gain Controller |
| 3551 | */ |
| 3552 | void |
| 3553 | bwi_phy_config_agc(struct bwi_mac *mac) |
| 3554 | { |
| 3555 | struct bwi_phy *phy = &mac->mac_phy; |
| 3556 | uint16_t ofs; |
| 3557 | |
| 3558 | ofs = phy->phy_rev == 1 ? 0x4c00 : 0; |
| 3559 | |
| 3560 | bwi_tbl_write_2(mac, ofs, 0xfe); |
| 3561 | bwi_tbl_write_2(mac, ofs + 1, 0xd); |
| 3562 | bwi_tbl_write_2(mac, ofs + 2, 0x13); |
| 3563 | bwi_tbl_write_2(mac, ofs + 3, 0x19); |
| 3564 | |
| 3565 | if (phy->phy_rev == 1) { |
| 3566 | bwi_tbl_write_2(mac, 0x1800, 0x2710); |
| 3567 | bwi_tbl_write_2(mac, 0x1801, 0x9b83); |
| 3568 | bwi_tbl_write_2(mac, 0x1802, 0x9b83); |
| 3569 | bwi_tbl_write_2(mac, 0x1803, 0xf8d); |
| 3570 | PHY_WRITE(mac, 0x455, 0x4)bwi_phy_write((mac), (0x455), (0x4)); |
| 3571 | } |
| 3572 | |
| 3573 | PHY_FILT_SETBITS(mac, 0x4a5, 0xff, 0x5700)bwi_phy_write(((mac)), ((0x4a5)), ((bwi_phy_read(((mac)), ((0x4a5 ))) & (0xff)) | (0x5700))); |
| 3574 | PHY_FILT_SETBITS(mac, 0x41a, 0xff80, 0xf)bwi_phy_write(((mac)), ((0x41a)), ((bwi_phy_read(((mac)), ((0x41a ))) & (0xff80)) | (0xf))); |
| 3575 | PHY_FILT_SETBITS(mac, 0x41a, 0xc07f, 0x2b80)bwi_phy_write(((mac)), ((0x41a)), ((bwi_phy_read(((mac)), ((0x41a ))) & (0xc07f)) | (0x2b80))); |
| 3576 | PHY_FILT_SETBITS(mac, 0x48c, 0xf0ff, 0x300)bwi_phy_write(((mac)), ((0x48c)), ((bwi_phy_read(((mac)), ((0x48c ))) & (0xf0ff)) | (0x300))); |
| 3577 | |
| 3578 | RF_SETBITS(mac, 0x7a, 0x8)bwi_rf_write(((mac)), ((0x7a)), (bwi_rf_read(((mac)), ((0x7a) )) | (0x8))); |
| 3579 | |
| 3580 | PHY_FILT_SETBITS(mac, 0x4a0, 0xfff0, 0x8)bwi_phy_write(((mac)), ((0x4a0)), ((bwi_phy_read(((mac)), ((0x4a0 ))) & (0xfff0)) | (0x8))); |
| 3581 | PHY_FILT_SETBITS(mac, 0x4a1, 0xf0ff, 0x600)bwi_phy_write(((mac)), ((0x4a1)), ((bwi_phy_read(((mac)), ((0x4a1 ))) & (0xf0ff)) | (0x600))); |
| 3582 | PHY_FILT_SETBITS(mac, 0x4a2, 0xf0ff, 0x700)bwi_phy_write(((mac)), ((0x4a2)), ((bwi_phy_read(((mac)), ((0x4a2 ))) & (0xf0ff)) | (0x700))); |
| 3583 | PHY_FILT_SETBITS(mac, 0x4a0, 0xf0ff, 0x100)bwi_phy_write(((mac)), ((0x4a0)), ((bwi_phy_read(((mac)), ((0x4a0 ))) & (0xf0ff)) | (0x100))); |
| 3584 | |
| 3585 | if (phy->phy_rev == 1) |
| 3586 | PHY_FILT_SETBITS(mac, 0x4a2, 0xfff0, 0x7)bwi_phy_write(((mac)), ((0x4a2)), ((bwi_phy_read(((mac)), ((0x4a2 ))) & (0xfff0)) | (0x7))); |
| 3587 | |
| 3588 | PHY_FILT_SETBITS(mac, 0x488, 0xff00, 0x1c)bwi_phy_write(((mac)), ((0x488)), ((bwi_phy_read(((mac)), ((0x488 ))) & (0xff00)) | (0x1c))); |
| 3589 | PHY_FILT_SETBITS(mac, 0x488, 0xc0ff, 0x200)bwi_phy_write(((mac)), ((0x488)), ((bwi_phy_read(((mac)), ((0x488 ))) & (0xc0ff)) | (0x200))); |
| 3590 | PHY_FILT_SETBITS(mac, 0x496, 0xff00, 0x1c)bwi_phy_write(((mac)), ((0x496)), ((bwi_phy_read(((mac)), ((0x496 ))) & (0xff00)) | (0x1c))); |
| 3591 | PHY_FILT_SETBITS(mac, 0x489, 0xff00, 0x20)bwi_phy_write(((mac)), ((0x489)), ((bwi_phy_read(((mac)), ((0x489 ))) & (0xff00)) | (0x20))); |
| 3592 | PHY_FILT_SETBITS(mac, 0x489, 0xc0ff, 0x200)bwi_phy_write(((mac)), ((0x489)), ((bwi_phy_read(((mac)), ((0x489 ))) & (0xc0ff)) | (0x200))); |
| 3593 | PHY_FILT_SETBITS(mac, 0x482, 0xff00, 0x2e)bwi_phy_write(((mac)), ((0x482)), ((bwi_phy_read(((mac)), ((0x482 ))) & (0xff00)) | (0x2e))); |
| 3594 | PHY_FILT_SETBITS(mac, 0x496, 0xff, 0x1a00)bwi_phy_write(((mac)), ((0x496)), ((bwi_phy_read(((mac)), ((0x496 ))) & (0xff)) | (0x1a00))); |
| 3595 | PHY_FILT_SETBITS(mac, 0x481, 0xff00, 0x28)bwi_phy_write(((mac)), ((0x481)), ((bwi_phy_read(((mac)), ((0x481 ))) & (0xff00)) | (0x28))); |
| 3596 | PHY_FILT_SETBITS(mac, 0x481, 0xff, 0x2c00)bwi_phy_write(((mac)), ((0x481)), ((bwi_phy_read(((mac)), ((0x481 ))) & (0xff)) | (0x2c00))); |
| 3597 | |
| 3598 | if (phy->phy_rev == 1) { |
| 3599 | PHY_WRITE(mac, 0x430, 0x92b)bwi_phy_write((mac), (0x430), (0x92b)); |
| 3600 | PHY_FILT_SETBITS(mac, 0x41b, 0xffe1, 0x2)bwi_phy_write(((mac)), ((0x41b)), ((bwi_phy_read(((mac)), ((0x41b ))) & (0xffe1)) | (0x2))); |
| 3601 | } else { |
| 3602 | PHY_CLRBITS(mac, 0x41b, 0x1e)bwi_phy_write(((mac)), ((0x41b)), (bwi_phy_read(((mac)), ((0x41b ))) & ~(0x1e))); |
| 3603 | PHY_WRITE(mac, 0x41f, 0x287a)bwi_phy_write((mac), (0x41f), (0x287a)); |
| 3604 | PHY_FILT_SETBITS(mac, 0x420, 0xfff0, 0x4)bwi_phy_write(((mac)), ((0x420)), ((bwi_phy_read(((mac)), ((0x420 ))) & (0xfff0)) | (0x4))); |
| 3605 | |
| 3606 | if (phy->phy_rev >= 6) { |
| 3607 | PHY_WRITE(mac, 0x422, 0x287a)bwi_phy_write((mac), (0x422), (0x287a)); |
| 3608 | PHY_FILT_SETBITS(mac, 0x420, 0xfff, 0x3000)bwi_phy_write(((mac)), ((0x420)), ((bwi_phy_read(((mac)), ((0x420 ))) & (0xfff)) | (0x3000))); |
| 3609 | } |
| 3610 | } |
| 3611 | |
| 3612 | PHY_FILT_SETBITS(mac, 0x4a8, 0x8080, 0x7874)bwi_phy_write(((mac)), ((0x4a8)), ((bwi_phy_read(((mac)), ((0x4a8 ))) & (0x8080)) | (0x7874))); |
| 3613 | PHY_WRITE(mac, 0x48e, 0x1c00)bwi_phy_write((mac), (0x48e), (0x1c00)); |
| 3614 | |
| 3615 | if (phy->phy_rev == 1) { |
| 3616 | PHY_FILT_SETBITS(mac, 0x4ab, 0xf0ff, 0x600)bwi_phy_write(((mac)), ((0x4ab)), ((bwi_phy_read(((mac)), ((0x4ab ))) & (0xf0ff)) | (0x600))); |
| 3617 | PHY_WRITE(mac, 0x48b, 0x5e)bwi_phy_write((mac), (0x48b), (0x5e)); |
| 3618 | PHY_FILT_SETBITS(mac, 0x48c, 0xff00, 0x1e)bwi_phy_write(((mac)), ((0x48c)), ((bwi_phy_read(((mac)), ((0x48c ))) & (0xff00)) | (0x1e))); |
| 3619 | PHY_WRITE(mac, 0x48d, 0x2)bwi_phy_write((mac), (0x48d), (0x2)); |
| 3620 | } |
| 3621 | |
| 3622 | bwi_tbl_write_2(mac, ofs + 0x800, 0); |
| 3623 | bwi_tbl_write_2(mac, ofs + 0x801, 7); |
| 3624 | bwi_tbl_write_2(mac, ofs + 0x802, 16); |
| 3625 | bwi_tbl_write_2(mac, ofs + 0x803, 28); |
| 3626 | |
| 3627 | if (phy->phy_rev >= 6) { |
| 3628 | PHY_CLRBITS(mac, 0x426, 0x3)bwi_phy_write(((mac)), ((0x426)), (bwi_phy_read(((mac)), ((0x426 ))) & ~(0x3))); |
| 3629 | PHY_CLRBITS(mac, 0x426, 0x1000)bwi_phy_write(((mac)), ((0x426)), (bwi_phy_read(((mac)), ((0x426 ))) & ~(0x1000))); |
| 3630 | } |
| 3631 | } |
| 3632 | |
| 3633 | void |
| 3634 | bwi_set_gains(struct bwi_mac *mac, const struct bwi_gains *gains) |
| 3635 | { |
| 3636 | struct bwi_phy *phy = &mac->mac_phy; |
| 3637 | uint16_t tbl_gain_ofs1, tbl_gain_ofs2, tbl_gain; |
| 3638 | int i; |
| 3639 | |
| 3640 | if (phy->phy_rev <= 1) { |
| 3641 | tbl_gain_ofs1 = 0x5000; |
| 3642 | tbl_gain_ofs2 = tbl_gain_ofs1 + 16; |
| 3643 | } else { |
| 3644 | tbl_gain_ofs1 = 0x400; |
| 3645 | tbl_gain_ofs2 = tbl_gain_ofs1 + 8; |
| 3646 | } |
| 3647 | |
| 3648 | for (i = 0; i < 4; ++i) { |
| 3649 | if (gains != NULL((void *)0)) { |
| 3650 | tbl_gain = gains->tbl_gain1; |
| 3651 | } else { |
| 3652 | /* Bit swap */ |
| 3653 | tbl_gain = (i & 0x1) << 1; |
| 3654 | tbl_gain |= (i & 0x2) >> 1; |
| 3655 | } |
| 3656 | bwi_tbl_write_2(mac, tbl_gain_ofs1 + i, tbl_gain); |
| 3657 | } |
| 3658 | |
| 3659 | for (i = 0; i < 16; ++i) { |
| 3660 | if (gains != NULL((void *)0)) |
| 3661 | tbl_gain = gains->tbl_gain2; |
| 3662 | else |
| 3663 | tbl_gain = i; |
| 3664 | bwi_tbl_write_2(mac, tbl_gain_ofs2 + i, tbl_gain); |
| 3665 | } |
| 3666 | |
| 3667 | if (gains == NULL((void *)0) || (gains != NULL((void *)0) && gains->phy_gain != -1)) { |
| 3668 | uint16_t phy_gain1, phy_gain2; |
| 3669 | |
| 3670 | if (gains != NULL((void *)0)) { |
| 3671 | phy_gain1 = |
| 3672 | ((uint16_t)gains->phy_gain << 14) | |
| 3673 | ((uint16_t)gains->phy_gain << 6); |
| 3674 | phy_gain2 = phy_gain1; |
| 3675 | } else { |
| 3676 | phy_gain1 = 0x4040; |
| 3677 | phy_gain2 = 0x4000; |
| 3678 | } |
| 3679 | PHY_FILT_SETBITS(mac, 0x4a0, 0xbfbf, phy_gain1)bwi_phy_write(((mac)), ((0x4a0)), ((bwi_phy_read(((mac)), ((0x4a0 ))) & (0xbfbf)) | (phy_gain1))); |
| 3680 | PHY_FILT_SETBITS(mac, 0x4a1, 0xbfbf, phy_gain1)bwi_phy_write(((mac)), ((0x4a1)), ((bwi_phy_read(((mac)), ((0x4a1 ))) & (0xbfbf)) | (phy_gain1))); |
| 3681 | PHY_FILT_SETBITS(mac, 0x4a2, 0xbfbf, phy_gain2)bwi_phy_write(((mac)), ((0x4a2)), ((bwi_phy_read(((mac)), ((0x4a2 ))) & (0xbfbf)) | (phy_gain2))); |
| 3682 | } |
| 3683 | bwi_mac_dummy_xmit(mac); |
| 3684 | } |
| 3685 | |
| 3686 | void |
| 3687 | bwi_phy_clear_state(struct bwi_phy *phy) |
| 3688 | { |
| 3689 | phy->phy_flags &= ~BWI_CLEAR_PHY_FLAGS(0x1); |
| 3690 | } |
| 3691 | |
| 3692 | /* RF */ |
| 3693 | |
| 3694 | int16_t |
| 3695 | bwi_nrssi_11g(struct bwi_mac *mac) |
| 3696 | { |
| 3697 | int16_t val; |
| 3698 | |
| 3699 | #define NRSSI_11G_MASK 0x3f00 |
| 3700 | val = (int16_t)__SHIFTOUT(PHY_READ(mac, 0x47f), NRSSI_11G_MASK)(((bwi_phy_read((mac), (0x47f))) & (NRSSI_11G_MASK)) / (( ((NRSSI_11G_MASK) - 1) & (NRSSI_11G_MASK)) ^ (NRSSI_11G_MASK ))); |
| 3701 | if (val >= 32) |
| 3702 | val -= 64; |
| 3703 | |
| 3704 | return (val); |
| 3705 | #undef NRSSI_11G_MASK |
| 3706 | } |
| 3707 | |
| 3708 | struct bwi_rf_lo * |
| 3709 | bwi_get_rf_lo(struct bwi_mac *mac, uint16_t rf_atten, uint16_t bbp_atten) |
| 3710 | { |
| 3711 | int n; |
| 3712 | |
| 3713 | n = rf_atten + (14 * (bbp_atten / 2)); |
| 3714 | KASSERT(n < BWI_RFLO_MAX)((n < 56) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c" , 3714, "n < BWI_RFLO_MAX")); |
| 3715 | |
| 3716 | return (&mac->mac_rf.rf_lo[n]); |
| 3717 | } |
| 3718 | |
| 3719 | int |
| 3720 | bwi_rf_lo_isused(struct bwi_mac *mac, const struct bwi_rf_lo *lo) |
| 3721 | { |
| 3722 | struct bwi_rf *rf = &mac->mac_rf; |
| 3723 | int idx; |
| 3724 | |
| 3725 | idx = lo - rf->rf_lo; |
| 3726 | KASSERT(idx >= 0 && idx < BWI_RFLO_MAX)((idx >= 0 && idx < 56) ? (void)0 : __assert("diagnostic " , "/usr/src/sys/dev/ic/bwi.c", 3726, "idx >= 0 && idx < BWI_RFLO_MAX" )); |
| 3727 | |
| 3728 | return (isset(rf->rf_lo_used, idx)((rf->rf_lo_used)[(idx)>>3] & (1<<((idx)& (8 -1))))); |
| 3729 | } |
| 3730 | |
| 3731 | void |
| 3732 | bwi_rf_write(struct bwi_mac *mac, uint16_t ctrl, uint16_t data) |
| 3733 | { |
| 3734 | struct bwi_softc *sc = mac->mac_sc; |
| 3735 | |
| 3736 | CSR_WRITE_2(sc, BWI_RF_CTRL, ctrl)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03f6 )), ((ctrl)))); |
| 3737 | CSR_WRITE_2(sc, BWI_RF_DATA_LO, data)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x3fa )), ((data)))); |
| 3738 | } |
| 3739 | |
| 3740 | uint16_t |
| 3741 | bwi_rf_read(struct bwi_mac *mac, uint16_t ctrl) |
| 3742 | { |
| 3743 | struct bwi_rf *rf = &mac->mac_rf; |
| 3744 | struct bwi_softc *sc = mac->mac_sc; |
| 3745 | |
| 3746 | ctrl |= rf->rf_ctrl_rd; |
| 3747 | if (rf->rf_ctrl_adj) { |
| 3748 | /* XXX */ |
| 3749 | if (ctrl < 0x70) |
| 3750 | ctrl += 0x80; |
| 3751 | else if (ctrl < 0x80) |
| 3752 | ctrl += 0x70; |
| 3753 | } |
| 3754 | |
| 3755 | CSR_WRITE_2(sc, BWI_RF_CTRL, ctrl)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03f6 )), ((ctrl)))); |
| 3756 | return (CSR_READ_2(sc, BWI_RF_DATA_LO)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x3fa ))))); |
| 3757 | } |
| 3758 | |
| 3759 | int |
| 3760 | bwi_rf_attach(struct bwi_mac *mac) |
| 3761 | { |
| 3762 | struct bwi_softc *sc = mac->mac_sc; |
| 3763 | struct bwi_phy *phy = &mac->mac_phy; |
| 3764 | 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 | if (sc->sc_bbp_id == BWI_BBPID_BCM43170x4317) { |
| 3772 | /* |
| 3773 | * Fake a BCM2050 RF |
| 3774 | */ |
| 3775 | manu = BWI_RF_MANUFACT_BCM0x17f; |
| 3776 | type = BWI_RF_T_BCM20500x2050; |
| 3777 | if (sc->sc_bbp_rev == 0) |
| 3778 | rev = 3; |
| 3779 | else if (sc->sc_bbp_rev == 1) |
| 3780 | rev = 4; |
| 3781 | else |
| 3782 | rev = 5; |
| 3783 | } else { |
| 3784 | uint32_t val; |
| 3785 | |
| 3786 | CSR_WRITE_2(sc, BWI_RF_CTRL, BWI_RF_CTRL_RFINFO)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03f6 )), ((0x1)))); |
| 3787 | val = CSR_READ_2(sc, BWI_RF_DATA_HI)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x3f8 )))); |
| 3788 | val <<= 16; |
| 3789 | |
| 3790 | CSR_WRITE_2(sc, BWI_RF_CTRL, BWI_RF_CTRL_RFINFO)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03f6 )), ((0x1)))); |
| 3791 | val |= CSR_READ_2(sc, BWI_RF_DATA_LO)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x3fa )))); |
| 3792 | |
| 3793 | manu = __SHIFTOUT(val, BWI_RFINFO_MANUFACT_MASK)(((val) & (0x0fff)) / ((((0x0fff) - 1) & (0x0fff)) ^ ( 0x0fff))); |
| 3794 | type = __SHIFTOUT(val, BWI_RFINFO_TYPE_MASK)(((val) & (0x0ffff000)) / ((((0x0ffff000) - 1) & (0x0ffff000 )) ^ (0x0ffff000))); |
| 3795 | rev = __SHIFTOUT(val, BWI_RFINFO_REV_MASK)(((val) & (0xf0000000)) / ((((0xf0000000) - 1) & (0xf0000000 )) ^ (0xf0000000))); |
| 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 | rf->rf_ctrl_rd = 0; |
| 3804 | rf->rf_ctrl_adj = 0; |
| 3805 | switch (phy->phy_mode) { |
| 3806 | case IEEE80211_MODE_11A: |
| 3807 | if (manu != BWI_RF_MANUFACT_BCM0x17f || |
| 3808 | type != BWI_RF_T_BCM20600x2060 || |
| 3809 | rev != 1) { |
| 3810 | printf("%s: only BCM2060 rev 1 RF is supported for " |
| 3811 | "11A PHY\n", sc->sc_dev.dv_xname); |
| 3812 | return (ENXIO6); |
| 3813 | } |
| 3814 | rf->rf_ctrl_rd = BWI_RF_CTRL_RD_11A0x40; |
| 3815 | rf->rf_on = bwi_rf_on_11a; |
| 3816 | rf->rf_off = bwi_rf_off_11a; |
| 3817 | rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2060; |
| 3818 | break; |
| 3819 | case IEEE80211_MODE_11B: |
| 3820 | if (type == BWI_RF_T_BCM20500x2050) { |
| 3821 | rf->rf_ctrl_rd = BWI_RF_CTRL_RD_11BG0x80; |
| 3822 | rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2050; |
| 3823 | } else if (type == BWI_RF_T_BCM20530x2053) { |
| 3824 | rf->rf_ctrl_adj = 1; |
| 3825 | rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2053; |
| 3826 | } else { |
| 3827 | printf("%s: only BCM2050/BCM2053 RF is supported " |
| 3828 | "for supported for 11B PHY\n", sc->sc_dev.dv_xname); |
| 3829 | return (ENXIO6); |
| 3830 | } |
| 3831 | rf->rf_on = bwi_rf_on_11bg; |
| 3832 | rf->rf_off = bwi_rf_off_11bg; |
| 3833 | rf->rf_calc_nrssi_slope = bwi_rf_calc_nrssi_slope_11b; |
| 3834 | rf->rf_set_nrssi_thr = bwi_rf_set_nrssi_thr_11b; |
| 3835 | if (phy->phy_rev == 6) |
| 3836 | rf->rf_lo_update = bwi_rf_lo_update_11g; |
| 3837 | else |
| 3838 | rf->rf_lo_update = bwi_rf_lo_update_11b; |
| 3839 | break; |
| 3840 | case IEEE80211_MODE_11G: |
| 3841 | if (type != BWI_RF_T_BCM20500x2050) { |
| 3842 | printf("%s: only BCM2050 RF is supported for 11G " |
| 3843 | "PHY\n", sc->sc_dev.dv_xname); |
| 3844 | return (ENXIO6); |
| 3845 | } |
| 3846 | rf->rf_ctrl_rd = BWI_RF_CTRL_RD_11BG0x80; |
| 3847 | rf->rf_on = bwi_rf_on_11bg; |
| 3848 | if (mac->mac_revmac_regwin.rw_rev >= 5) |
| 3849 | rf->rf_off = bwi_rf_off_11g_rev5; |
| 3850 | else |
| 3851 | rf->rf_off = bwi_rf_off_11bg; |
| 3852 | rf->rf_calc_nrssi_slope = bwi_rf_calc_nrssi_slope_11g; |
| 3853 | rf->rf_set_nrssi_thr = bwi_rf_set_nrssi_thr_11g; |
| 3854 | rf->rf_calc_rssi = bwi_rf_calc_rssi_bcm2050; |
| 3855 | rf->rf_lo_update = bwi_rf_lo_update_11g; |
| 3856 | break; |
| 3857 | default: |
| 3858 | printf("%s: unsupported PHY mode\n", sc->sc_dev.dv_xname); |
| 3859 | return (ENXIO6); |
| 3860 | } |
| 3861 | |
| 3862 | rf->rf_type = type; |
| 3863 | rf->rf_rev = rev; |
| 3864 | rf->rf_manu = manu; |
| 3865 | rf->rf_curchan = IEEE80211_CHAN_ANY0xffff; |
| 3866 | rf->rf_ant_mode = BWI_ANT_MODE_AUTO3; |
| 3867 | |
| 3868 | return (0); |
| 3869 | } |
| 3870 | |
| 3871 | void |
| 3872 | bwi_rf_set_chan(struct bwi_mac *mac, uint chan, int work_around) |
| 3873 | { |
| 3874 | struct bwi_softc *sc = mac->mac_sc; |
| 3875 | |
| 3876 | if (chan == IEEE80211_CHAN_ANY0xffff) |
| 3877 | return; |
| 3878 | |
| 3879 | MOBJ_WRITE_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_CHAN, chan)bwi_memobj_write_2((mac), (0x1), (0xa0), (chan)); |
| 3880 | |
| 3881 | /* TODO: 11A */ |
| 3882 | |
| 3883 | if (work_around) |
| 3884 | bwi_rf_workaround(mac, chan); |
| 3885 | |
| 3886 | CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(chan))(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03f0 )), (((ieee80211_ieee2mhz((chan), 0x0080) - 2400))))); |
| 3887 | |
| 3888 | if (chan == 14) { |
| 3889 | if (sc->sc_locale == BWI_SPROM_LOCALE_JAPAN5) |
| 3890 | HFLAGS_CLRBITS(mac, BWI_HFLAG_NOT_JAPAN)bwi_hostflags_write(((mac)), (bwi_hostflags_read(((mac))) | ( 0x80ULL))); |
| 3891 | else |
| 3892 | HFLAGS_SETBITS(mac, BWI_HFLAG_NOT_JAPAN)bwi_hostflags_write(((mac)), (bwi_hostflags_read(((mac))) & ~(0x80ULL))); |
| 3893 | CSR_SETBITS_2(sc, BWI_RF_CHAN_EX, (1 << 11))((((sc))->sc_mem_bt)->write_2((((sc))->sc_mem_bh), ( ((0x03f4))), ((((((sc))->sc_mem_bt)->read_2((((sc))-> sc_mem_bh), (((0x03f4))))) | ((1 << 11)))))); /* XXX */ |
| 3894 | } else { |
| 3895 | CSR_CLRBITS_2(sc, BWI_RF_CHAN_EX, 0x840)((((sc))->sc_mem_bt)->write_2((((sc))->sc_mem_bh), ( ((0x03f4))), ((((((sc))->sc_mem_bt)->read_2((((sc))-> sc_mem_bh), (((0x03f4))))) & ~(0x840))))); /* XXX */ |
| 3896 | } |
| 3897 | DELAY(8000)(*delay_func)(8000); /* DELAY(2000); */ |
| 3898 | |
| 3899 | mac->mac_rf.rf_curchan = chan; |
| 3900 | } |
| 3901 | |
| 3902 | void |
| 3903 | 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 | struct bwi_phy *phy = &mac->mac_phy; |
| 3909 | struct bwi_rf *rf = &mac->mac_rf; |
| 3910 | uint16_t save_phy[SAVE_PHY_MAX]; |
| 3911 | 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 | sc = mac->mac_sc; |
| 3925 | |
| 3926 | /* |
| 3927 | * Save PHY/RF registers for later restoration |
| 3928 | */ |
| 3929 | for (i = 0; i < SAVE_PHY_MAX; ++i) |
| 3930 | save_phy[i] = PHY_READ(mac, save_phy_regs[i])bwi_phy_read((mac), (save_phy_regs[i])); |
| 3931 | PHY_READ(mac, 0x2d)bwi_phy_read((mac), (0x2d)); /* dummy read */ |
| 3932 | |
| 3933 | for (i = 0; i < SAVE_RF_MAX; ++i) |
| 3934 | save_rf[i] = RF_READ(mac, save_rf_regs[i])bwi_rf_read((mac), (save_rf_regs[i])); |
| 3935 | |
| 3936 | PHY_CLRBITS(mac, 0x429, 0xc000)bwi_phy_write(((mac)), ((0x429)), (bwi_phy_read(((mac)), ((0x429 ))) & ~(0xc000))); |
| 3937 | PHY_SETBITS(mac, 0x1, 0x8000)bwi_phy_write(((mac)), ((0x1)), (bwi_phy_read(((mac)), ((0x1) )) | (0x8000))); |
| 3938 | |
| 3939 | PHY_SETBITS(mac, 0x811, 0x2)bwi_phy_write(((mac)), ((0x811)), (bwi_phy_read(((mac)), ((0x811 ))) | (0x2))); |
| 3940 | PHY_CLRBITS(mac, 0x812, 0x2)bwi_phy_write(((mac)), ((0x812)), (bwi_phy_read(((mac)), ((0x812 ))) & ~(0x2))); |
| 3941 | PHY_SETBITS(mac, 0x811, 0x1)bwi_phy_write(((mac)), ((0x811)), (bwi_phy_read(((mac)), ((0x811 ))) | (0x1))); |
| 3942 | PHY_CLRBITS(mac, 0x812, 0x1)bwi_phy_write(((mac)), ((0x812)), (bwi_phy_read(((mac)), ((0x812 ))) & ~(0x1))); |
| 3943 | |
| 3944 | PHY_SETBITS(mac, 0x814, 0x1)bwi_phy_write(((mac)), ((0x814)), (bwi_phy_read(((mac)), ((0x814 ))) | (0x1))); |
| 3945 | PHY_CLRBITS(mac, 0x815, 0x1)bwi_phy_write(((mac)), ((0x815)), (bwi_phy_read(((mac)), ((0x815 ))) & ~(0x1))); |
| 3946 | PHY_SETBITS(mac, 0x814, 0x2)bwi_phy_write(((mac)), ((0x814)), (bwi_phy_read(((mac)), ((0x814 ))) | (0x2))); |
| 3947 | PHY_CLRBITS(mac, 0x815, 0x2)bwi_phy_write(((mac)), ((0x815)), (bwi_phy_read(((mac)), ((0x815 ))) & ~(0x2))); |
| 3948 | |
| 3949 | PHY_SETBITS(mac, 0x811, 0xc)bwi_phy_write(((mac)), ((0x811)), (bwi_phy_read(((mac)), ((0x811 ))) | (0xc))); |
| 3950 | PHY_SETBITS(mac, 0x812, 0xc)bwi_phy_write(((mac)), ((0x812)), (bwi_phy_read(((mac)), ((0x812 ))) | (0xc))); |
| 3951 | PHY_SETBITS(mac, 0x811, 0x30)bwi_phy_write(((mac)), ((0x811)), (bwi_phy_read(((mac)), ((0x811 ))) | (0x30))); |
| 3952 | PHY_FILT_SETBITS(mac, 0x812, 0xffcf, 0x10)bwi_phy_write(((mac)), ((0x812)), ((bwi_phy_read(((mac)), ((0x812 ))) & (0xffcf)) | (0x10))); |
| 3953 | |
| 3954 | PHY_WRITE(mac, 0x5a, 0x780)bwi_phy_write((mac), (0x5a), (0x780)); |
| 3955 | PHY_WRITE(mac, 0x59, 0xc810)bwi_phy_write((mac), (0x59), (0xc810)); |
| 3956 | PHY_WRITE(mac, 0x58, 0xd)bwi_phy_write((mac), (0x58), (0xd)); |
| 3957 | PHY_SETBITS(mac, 0xa, 0x2000)bwi_phy_write(((mac)), ((0xa)), (bwi_phy_read(((mac)), ((0xa) )) | (0x2000))); |
| 3958 | |
| 3959 | PHY_SETBITS(mac, 0x814, 0x4)bwi_phy_write(((mac)), ((0x814)), (bwi_phy_read(((mac)), ((0x814 ))) | (0x4))); |
| 3960 | PHY_CLRBITS(mac, 0x815, 0x4)bwi_phy_write(((mac)), ((0x815)), (bwi_phy_read(((mac)), ((0x815 ))) & ~(0x4))); |
| 3961 | |
| 3962 | PHY_FILT_SETBITS(mac, 0x3, 0xff9f, 0x40)bwi_phy_write(((mac)), ((0x3)), ((bwi_phy_read(((mac)), ((0x3 ))) & (0xff9f)) | (0x40))); |
| 3963 | |
| 3964 | if (rf->rf_rev == 8) { |
| 3965 | loop1_max = 15; |
| 3966 | RF_WRITE(mac, 0x43, loop1_max)bwi_rf_write((mac), (0x43), (loop1_max)); |
| 3967 | } else { |
| 3968 | loop1_max = 9; |
| 3969 | RF_WRITE(mac, 0x52, 0x0)bwi_rf_write((mac), (0x52), (0x0)); |
| 3970 | RF_FILT_SETBITS(mac, 0x43, 0xfff0, loop1_max)bwi_rf_write(((mac)), ((0x43)), ((bwi_rf_read(((mac)), ((0x43 ))) & (0xfff0)) | (loop1_max))); |
| 3971 | } |
| 3972 | |
| 3973 | bwi_phy_set_bbp_atten(mac, 11); |
| 3974 | |
| 3975 | if (phy->phy_rev >= 3) |
| 3976 | PHY_WRITE(mac, 0x80f, 0xc020)bwi_phy_write((mac), (0x80f), (0xc020)); |
| 3977 | else |
| 3978 | PHY_WRITE(mac, 0x80f, 0x8020)bwi_phy_write((mac), (0x80f), (0x8020)); |
| 3979 | PHY_WRITE(mac, 0x810, 0)bwi_phy_write((mac), (0x810), (0)); |
| 3980 | |
| 3981 | PHY_FILT_SETBITS(mac, 0x2b, 0xffc0, 0x1)bwi_phy_write(((mac)), ((0x2b)), ((bwi_phy_read(((mac)), ((0x2b ))) & (0xffc0)) | (0x1))); |
| 3982 | PHY_FILT_SETBITS(mac, 0x2b, 0xc0ff, 0x800)bwi_phy_write(((mac)), ((0x2b)), ((bwi_phy_read(((mac)), ((0x2b ))) & (0xc0ff)) | (0x800))); |
| 3983 | PHY_SETBITS(mac, 0x811, 0x100)bwi_phy_write(((mac)), ((0x811)), (bwi_phy_read(((mac)), ((0x811 ))) | (0x100))); |
| 3984 | PHY_CLRBITS(mac, 0x812, 0x3000)bwi_phy_write(((mac)), ((0x812)), (bwi_phy_read(((mac)), ((0x812 ))) & ~(0x3000))); |
| 3985 | |
| 3986 | if ((mac->mac_sc->sc_card_flags & BWI_CARD_F_EXT_LNA(1 << 12)) && |
| 3987 | phy->phy_rev >= 7) { |
| 3988 | PHY_SETBITS(mac, 0x811, 0x800)bwi_phy_write(((mac)), ((0x811)), (bwi_phy_read(((mac)), ((0x811 ))) | (0x800))); |
| 3989 | PHY_SETBITS(mac, 0x812, 0x8000)bwi_phy_write(((mac)), ((0x812)), (bwi_phy_read(((mac)), ((0x812 ))) | (0x8000))); |
| 3990 | } |
| 3991 | RF_CLRBITS(mac, 0x7a, 0xff08)bwi_rf_write(((mac)), ((0x7a)), (bwi_rf_read(((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 | for (i = 0; i < loop1_max; ++i) { |
| 3999 | for (j = 0; j < 16; ++j) { |
| 4000 | RF_WRITE(mac, 0x43, i)bwi_rf_write((mac), (0x43), (i)); |
| 4001 | |
| 4002 | 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 | if (loop2 >= 8) { |
| 4015 | PHY_SETBITS(mac, 0x812, 0x30)bwi_phy_write(((mac)), ((0x812)), (bwi_phy_read(((mac)), ((0x812 ))) | (0x30))); |
| 4016 | trsw = 0x1b; |
| 4017 | for (i = loop2 - 8; i < 16; ++i) { |
| 4018 | trsw -= 3; |
| 4019 | 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 | for (i = 4; i < SAVE_PHY_MAX; ++i) |
| 4031 | PHY_WRITE(mac, save_phy_regs[i], save_phy[i])bwi_phy_write((mac), (save_phy_regs[i]), (save_phy[i])); |
| 4032 | |
| 4033 | bwi_phy_set_bbp_atten(mac, mac->mac_tpctl.bbp_atten); |
| 4034 | |
| 4035 | for (i = 0; i < SAVE_RF_MAX; ++i) |
| 4036 | RF_WRITE(mac, save_rf_regs[i], save_rf[i])bwi_rf_write((mac), (save_rf_regs[i]), (save_rf[i])); |
| 4037 | |
| 4038 | PHY_WRITE(mac, save_phy_regs[2], save_phy[2] | 0x3)bwi_phy_write((mac), (save_phy_regs[2]), (save_phy[2] | 0x3)); |
| 4039 | DELAY(10)(*delay_func)(10); |
| 4040 | PHY_WRITE(mac, save_phy_regs[2], save_phy[2])bwi_phy_write((mac), (save_phy_regs[2]), (save_phy[2])); |
| 4041 | PHY_WRITE(mac, save_phy_regs[3], save_phy[3])bwi_phy_write((mac), (save_phy_regs[3]), (save_phy[3])); |
| 4042 | PHY_WRITE(mac, save_phy_regs[0], save_phy[0])bwi_phy_write((mac), (save_phy_regs[0]), (save_phy[0])); |
| 4043 | PHY_WRITE(mac, save_phy_regs[1], save_phy[1])bwi_phy_write((mac), (save_phy_regs[1]), (save_phy[1])); |
| 4044 | |
| 4045 | /* |
| 4046 | * Calculate gains |
| 4047 | */ |
| 4048 | rf->rf_lo_gain = (loop2 * 6) - (loop1 * 4) - 11; |
| 4049 | 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 | } |
| 4056 | |
| 4057 | void |
| 4058 | bwi_rf_init(struct bwi_mac *mac) |
| 4059 | { |
| 4060 | struct bwi_rf *rf = &mac->mac_rf; |
| 4061 | |
| 4062 | if (rf->rf_type == BWI_RF_T_BCM20600x2060) { |
| 4063 | /* TODO: 11A */ |
| 4064 | } else { |
| 4065 | if (rf->rf_flags & BWI_RF_F_INITED0x1) |
| 4066 | RF_WRITE(mac, 0x78, rf->rf_calib)bwi_rf_write((mac), (0x78), (rf->rf_calib)); |
| 4067 | else |
| 4068 | bwi_rf_init_bcm2050(mac); |
| 4069 | } |
| 4070 | } |
| 4071 | |
| 4072 | void |
| 4073 | bwi_rf_off_11a(struct bwi_mac *mac) |
| 4074 | { |
| 4075 | RF_WRITE(mac, 0x4, 0xff)bwi_rf_write((mac), (0x4), (0xff)); |
| 4076 | RF_WRITE(mac, 0x5, 0xfb)bwi_rf_write((mac), (0x5), (0xfb)); |
| 4077 | |
| 4078 | PHY_SETBITS(mac, 0x10, 0x8)bwi_phy_write(((mac)), ((0x10)), (bwi_phy_read(((mac)), ((0x10 ))) | (0x8))); |
| 4079 | PHY_SETBITS(mac, 0x11, 0x8)bwi_phy_write(((mac)), ((0x11)), (bwi_phy_read(((mac)), ((0x11 ))) | (0x8))); |
| 4080 | |
| 4081 | PHY_WRITE(mac, 0x15, 0xaa00)bwi_phy_write((mac), (0x15), (0xaa00)); |
| 4082 | } |
| 4083 | |
| 4084 | void |
| 4085 | bwi_rf_off_11bg(struct bwi_mac *mac) |
| 4086 | { |
| 4087 | PHY_WRITE(mac, 0x15, 0xaa00)bwi_phy_write((mac), (0x15), (0xaa00)); |
| 4088 | } |
| 4089 | |
| 4090 | void |
| 4091 | bwi_rf_off_11g_rev5(struct bwi_mac *mac) |
| 4092 | { |
| 4093 | PHY_SETBITS(mac, 0x811, 0x8c)bwi_phy_write(((mac)), ((0x811)), (bwi_phy_read(((mac)), ((0x811 ))) | (0x8c))); |
| 4094 | PHY_CLRBITS(mac, 0x812, 0x8c)bwi_phy_write(((mac)), ((0x812)), (bwi_phy_read(((mac)), ((0x812 ))) & ~(0x8c))); |
| 4095 | } |
| 4096 | |
| 4097 | void |
| 4098 | bwi_rf_workaround(struct bwi_mac *mac, uint chan) |
| 4099 | { |
| 4100 | struct bwi_softc *sc = mac->mac_sc; |
| 4101 | struct bwi_rf *rf = &mac->mac_rf; |
| 4102 | |
| 4103 | if (chan == IEEE80211_CHAN_ANY0xffff) { |
| 4104 | printf("%s: %s invalid channel!\n", |
| 4105 | sc->sc_dev.dv_xname, __func__); |
| 4106 | return; |
| 4107 | } |
| 4108 | |
| 4109 | if (rf->rf_type != BWI_RF_T_BCM20500x2050 || rf->rf_rev >= 6) |
| 4110 | return; |
| 4111 | |
| 4112 | if (chan <= 10) |
| 4113 | CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(chan + 4))(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03f0 )), (((ieee80211_ieee2mhz((chan + 4), 0x0080) - 2400))))); |
| 4114 | else |
| 4115 | CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(1))(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03f0 )), (((ieee80211_ieee2mhz((1), 0x0080) - 2400))))); |
| 4116 | DELAY(1000)(*delay_func)(1000); |
| 4117 | CSR_WRITE_2(sc, BWI_RF_CHAN, BWI_RF_2GHZ_CHAN(chan))(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03f0 )), (((ieee80211_ieee2mhz((chan), 0x0080) - 2400))))); |
| 4118 | } |
| 4119 | |
| 4120 | struct bwi_rf_lo * |
| 4121 | 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 | if (tpctl == NULL((void *)0)) { |
| 4128 | bbp_atten = 2; |
| 4129 | rf_atten = 3; |
| 4130 | } else { |
| 4131 | if (tpctl->tp_ctrl1 == 3) |
| 4132 | remap_rf_atten = 0; |
| 4133 | |
| 4134 | bbp_atten = tpctl->bbp_atten; |
| 4135 | rf_atten = tpctl->rf_atten; |
| 4136 | |
| 4137 | if (bbp_atten > 6) |
| 4138 | bbp_atten = 6; |
| 4139 | } |
| 4140 | |
| 4141 | 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)((rf_atten < MAP_MAX) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c" , 4146, "rf_atten < MAP_MAX")); |
| 4147 | rf_atten = map[rf_atten]; |
| 4148 | #else |
| 4149 | if (rf_atten >= MAP_MAX) { |
| 4150 | rf_atten = 0; /* XXX */ |
| 4151 | } else { |
| 4152 | rf_atten = map[rf_atten]; |
| 4153 | } |
| 4154 | #endif |
| 4155 | #undef MAP_MAX |
| 4156 | } |
| 4157 | |
| 4158 | return (bwi_get_rf_lo(mac, rf_atten, bbp_atten)); |
| 4159 | } |
| 4160 | |
| 4161 | void |
| 4162 | bwi_rf_lo_adjust(struct bwi_mac *mac, const struct bwi_tpctl *tpctl) |
| 4163 | { |
| 4164 | const struct bwi_rf_lo *lo; |
| 4165 | |
| 4166 | lo = bwi_rf_lo_find(mac, tpctl); |
| 4167 | RF_LO_WRITE(mac, lo)bwi_rf_lo_write((mac), (lo)); |
| 4168 | } |
| 4169 | |
| 4170 | void |
| 4171 | bwi_rf_lo_write(struct bwi_mac *mac, const struct bwi_rf_lo *lo) |
| 4172 | { |
| 4173 | uint16_t val; |
| 4174 | |
| 4175 | val = (uint8_t)lo->ctrl_lo; |
| 4176 | val |= ((uint8_t)lo->ctrl_hi) << 8; |
| 4177 | |
| 4178 | PHY_WRITE(mac, BWI_PHYR_RF_LO, val)bwi_phy_write((mac), (0x810), (val)); |
| 4179 | } |
| 4180 | |
| 4181 | int |
| 4182 | bwi_rf_gain_max_reached(struct bwi_mac *mac, int idx) |
| 4183 | { |
| 4184 | PHY_FILT_SETBITS(mac, 0x812, 0xf0ff, idx << 8)bwi_phy_write(((mac)), ((0x812)), ((bwi_phy_read(((mac)), ((0x812 ))) & (0xf0ff)) | (idx << 8))); |
| 4185 | PHY_FILT_SETBITS(mac, 0x15, 0xfff, 0xa000)bwi_phy_write(((mac)), ((0x15)), ((bwi_phy_read(((mac)), ((0x15 ))) & (0xfff)) | (0xa000))); |
| 4186 | PHY_SETBITS(mac, 0x15, 0xf000)bwi_phy_write(((mac)), ((0x15)), (bwi_phy_read(((mac)), ((0x15 ))) | (0xf000))); |
| 4187 | |
| 4188 | DELAY(20)(*delay_func)(20); |
| 4189 | |
| 4190 | return ((PHY_READ(mac, 0x2d)bwi_phy_read((mac), (0x2d)) >= 0xdfc)); |
| 4191 | } |
| 4192 | |
| 4193 | /* XXX use bitmap array */ |
| 4194 | uint16_t |
| 4195 | bwi_bitswap4(uint16_t val) |
| 4196 | { |
| 4197 | uint16_t ret; |
| 4198 | |
| 4199 | ret = (val & 0x8) >> 3; |
| 4200 | ret |= (val & 0x4) >> 1; |
| 4201 | ret |= (val & 0x2) << 1; |
| 4202 | ret |= (val & 0x1) << 3; |
| 4203 | |
| 4204 | return (ret); |
| 4205 | } |
| 4206 | |
| 4207 | uint16_t |
| 4208 | bwi_phy812_value(struct bwi_mac *mac, uint16_t lpd) |
| 4209 | { |
| 4210 | struct bwi_softc *sc = mac->mac_sc; |
| 4211 | struct bwi_phy *phy = &mac->mac_phy; |
| 4212 | struct bwi_rf *rf = &mac->mac_rf; |
| 4213 | uint16_t lo_gain, ext_lna, loop; |
| 4214 | |
| 4215 | if ((phy->phy_flags & BWI_PHY_F_LINKED0x2) == 0) |
| 4216 | return (0); |
| 4217 | |
| 4218 | lo_gain = rf->rf_lo_gain; |
| 4219 | if (rf->rf_rev == 8) |
| 4220 | lo_gain += 0x3e; |
| 4221 | else |
| 4222 | lo_gain += 0x26; |
| 4223 | |
| 4224 | if (lo_gain >= 0x46) { |
| 4225 | lo_gain -= 0x46; |
| 4226 | ext_lna = 0x3000; |
| 4227 | } else if (lo_gain >= 0x3a) { |
| 4228 | lo_gain -= 0x3a; |
| 4229 | ext_lna = 0x1000; |
| 4230 | } else if (lo_gain >= 0x2e) { |
| 4231 | lo_gain -= 0x2e; |
| 4232 | ext_lna = 0x2000; |
| 4233 | } else { |
| 4234 | lo_gain -= 0x10; |
| 4235 | ext_lna = 0; |
| 4236 | } |
| 4237 | |
| 4238 | for (loop = 0; loop < 16; ++loop) { |
| 4239 | lo_gain -= (6 * loop); |
| 4240 | if (lo_gain < 6) |
| 4241 | break; |
| 4242 | } |
| 4243 | |
| 4244 | if (phy->phy_rev >= 7 && (sc->sc_card_flags & BWI_CARD_F_EXT_LNA(1 << 12))) { |
| 4245 | if (ext_lna) |
| 4246 | ext_lna |= 0x8000; |
| 4247 | ext_lna |= (loop << 8); |
| 4248 | switch (lpd) { |
| 4249 | case 0x011: |
| 4250 | return (0x8f92); |
| 4251 | case 0x001: |
| 4252 | return ((0x8092 | ext_lna)); |
| 4253 | case 0x101: |
| 4254 | return ((0x2092 | ext_lna)); |
| 4255 | case 0x100: |
| 4256 | return ((0x2093 | ext_lna)); |
| 4257 | default: |
| 4258 | panic("unsupported lpd"); |
| 4259 | } |
| 4260 | } else { |
| 4261 | ext_lna |= (loop << 8); |
| 4262 | switch (lpd) { |
| 4263 | case 0x011: |
| 4264 | return (0xf92); |
| 4265 | case 0x001: |
| 4266 | case 0x101: |
| 4267 | return ((0x92 | ext_lna)); |
| 4268 | case 0x100: |
| 4269 | return ((0x93 | ext_lna)); |
| 4270 | default: |
| 4271 | panic("unsupported lpd"); |
| 4272 | } |
| 4273 | } |
| 4274 | |
| 4275 | panic("never reached"); |
| 4276 | |
| 4277 | return (0); |
| 4278 | } |
| 4279 | |
| 4280 | void |
| 4281 | 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 | uint16_t save_rf[SAVE_RF_MAX]; |
| 4287 | uint16_t save_phy_comm[SAVE_PHY_COMM_MAX]; |
| 4288 | 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 | struct bwi_softc *sc = mac->mac_sc; |
| 4295 | struct bwi_phy *phy = &mac->mac_phy; |
| 4296 | 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 | for (i = 0; i < SAVE_RF_MAX; ++i) |
| 4310 | save_rf[i] = RF_READ(mac, save_rf_regs[i])bwi_rf_read((mac), (save_rf_regs[i])); |
| 4311 | for (i = 0; i < SAVE_PHY_COMM_MAX; ++i) |
| 4312 | save_phy_comm[i] = PHY_READ(mac, save_phy_regs_comm[i])bwi_phy_read((mac), (save_phy_regs_comm[i])); |
| 4313 | |
| 4314 | if (phy->phy_mode == IEEE80211_MODE_11B) { |
| 4315 | phyr_30 = PHY_READ(mac, 0x30)bwi_phy_read((mac), (0x30)); |
| 4316 | bphy_ctrl = CSR_READ_2(sc, BWI_BPHY_CTRL)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x03ec )))); |
| 4317 | |
| 4318 | PHY_WRITE(mac, 0x30, 0xff)bwi_phy_write((mac), (0x30), (0xff)); |
| 4319 | CSR_WRITE_2(sc, BWI_BPHY_CTRL, 0x3f3f)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03ec )), ((0x3f3f)))); |
| 4320 | } else if ((phy->phy_flags & BWI_PHY_F_LINKED0x2) || phy->phy_rev >= 2) { |
| 4321 | for (i = 0; i < SAVE_PHY_11G_MAX; ++i) { |
| 4322 | save_phy_11g[i] = |
| 4323 | PHY_READ(mac, save_phy_regs_11g[i])bwi_phy_read((mac), (save_phy_regs_11g[i])); |
| 4324 | } |
| 4325 | |
| 4326 | PHY_SETBITS(mac, 0x814, 0x3)bwi_phy_write(((mac)), ((0x814)), (bwi_phy_read(((mac)), ((0x814 ))) | (0x3))); |
| 4327 | PHY_CLRBITS(mac, 0x815, 0x3)bwi_phy_write(((mac)), ((0x815)), (bwi_phy_read(((mac)), ((0x815 ))) & ~(0x3))); |
| 4328 | PHY_CLRBITS(mac, 0x429, 0x8000)bwi_phy_write(((mac)), ((0x429)), (bwi_phy_read(((mac)), ((0x429 ))) & ~(0x8000))); |
| 4329 | PHY_CLRBITS(mac, 0x802, 0x3)bwi_phy_write(((mac)), ((0x802)), (bwi_phy_read(((mac)), ((0x802 ))) & ~(0x3))); |
| 4330 | |
| 4331 | phyr_80f = PHY_READ(mac, 0x80f)bwi_phy_read((mac), (0x80f)); |
| 4332 | phyr_810 = PHY_READ(mac, 0x810)bwi_phy_read((mac), (0x810)); |
| 4333 | |
| 4334 | if (phy->phy_rev >= 3) |
| 4335 | PHY_WRITE(mac, 0x80f, 0xc020)bwi_phy_write((mac), (0x80f), (0xc020)); |
| 4336 | else |
| 4337 | PHY_WRITE(mac, 0x80f, 0x8020)bwi_phy_write((mac), (0x80f), (0x8020)); |
| 4338 | PHY_WRITE(mac, 0x810, 0)bwi_phy_write((mac), (0x810), (0)); |
| 4339 | |
| 4340 | phy812_val = bwi_phy812_value(mac, 0x011); |
| 4341 | PHY_WRITE(mac, 0x812, phy812_val)bwi_phy_write((mac), (0x812), (phy812_val)); |
| 4342 | if (phy->phy_rev < 7 || |
| 4343 | (sc->sc_card_flags & BWI_CARD_F_EXT_LNA(1 << 12)) == 0) |
| 4344 | PHY_WRITE(mac, 0x811, 0x1b3)bwi_phy_write((mac), (0x811), (0x1b3)); |
| 4345 | else |
| 4346 | PHY_WRITE(mac, 0x811, 0x9b3)bwi_phy_write((mac), (0x811), (0x9b3)); |
| 4347 | } |
| 4348 | CSR_SETBITS_2(sc, BWI_RF_ANTDIV, 0x8000)((((sc))->sc_mem_bt)->write_2((((sc))->sc_mem_bh), ( ((0x03e2))), ((((((sc))->sc_mem_bt)->read_2((((sc))-> sc_mem_bh), (((0x03e2))))) | (0x8000))))); |
| 4349 | |
| 4350 | phyr_35 = PHY_READ(mac, 0x35)bwi_phy_read((mac), (0x35)); |
| 4351 | PHY_CLRBITS(mac, 0x35, 0x80)bwi_phy_write(((mac)), ((0x35)), (bwi_phy_read(((mac)), ((0x35 ))) & ~(0x80))); |
| 4352 | |
| 4353 | bbp_atten = CSR_READ_2(sc, BWI_BBP_ATTEN)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x03e6 )))); |
| 4354 | rf_chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x03f4 )))); |
| 4355 | |
| 4356 | if (phy->phy_version == 0) { |
| 4357 | CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0x122)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03e6 )), ((0x122)))); |
| 4358 | } else { |
| 4359 | if (phy->phy_version >= 2) |
| 4360 | PHY_FILT_SETBITS(mac, 0x3, 0xffbf, 0x40)bwi_phy_write(((mac)), ((0x3)), ((bwi_phy_read(((mac)), ((0x3 ))) & (0xffbf)) | (0x40))); |
| 4361 | CSR_SETBITS_2(sc, BWI_RF_CHAN_EX, 0x2000)((((sc))->sc_mem_bt)->write_2((((sc))->sc_mem_bh), ( ((0x03f4))), ((((((sc))->sc_mem_bt)->read_2((((sc))-> sc_mem_bh), (((0x03f4))))) | (0x2000))))); |
| 4362 | } |
| 4363 | |
| 4364 | calib = bwi_rf_calibval(mac); |
| 4365 | |
| 4366 | if (phy->phy_mode == IEEE80211_MODE_11B) |
| 4367 | RF_WRITE(mac, 0x78, 0x26)bwi_rf_write((mac), (0x78), (0x26)); |
| 4368 | |
| 4369 | if ((phy->phy_flags & BWI_PHY_F_LINKED0x2) || phy->phy_rev >= 2) { |
| 4370 | phy812_val = bwi_phy812_value(mac, 0x011); |
| 4371 | PHY_WRITE(mac, 0x812, phy812_val)bwi_phy_write((mac), (0x812), (phy812_val)); |
| 4372 | } |
| 4373 | |
| 4374 | PHY_WRITE(mac, 0x15, 0xbfaf)bwi_phy_write((mac), (0x15), (0xbfaf)); |
| 4375 | PHY_WRITE(mac, 0x2b, 0x1403)bwi_phy_write((mac), (0x2b), (0x1403)); |
| 4376 | |
| 4377 | if ((phy->phy_flags & BWI_PHY_F_LINKED0x2) || phy->phy_rev >= 2) { |
| 4378 | phy812_val = bwi_phy812_value(mac, 0x001); |
| 4379 | PHY_WRITE(mac, 0x812, phy812_val)bwi_phy_write((mac), (0x812), (phy812_val)); |
| 4380 | } |
| 4381 | |
| 4382 | PHY_WRITE(mac, 0x15, 0xbfa0)bwi_phy_write((mac), (0x15), (0xbfa0)); |
| 4383 | |
| 4384 | RF_SETBITS(mac, 0x51, 0x4)bwi_rf_write(((mac)), ((0x51)), (bwi_rf_read(((mac)), ((0x51) )) | (0x4))); |
| 4385 | if (rf->rf_rev == 8) |
| 4386 | RF_WRITE(mac, 0x43, 0x1f)bwi_rf_write((mac), (0x43), (0x1f)); |
| 4387 | else { |
| 4388 | RF_WRITE(mac, 0x52, 0)bwi_rf_write((mac), (0x52), (0)); |
| 4389 | RF_FILT_SETBITS(mac, 0x43, 0xfff0, 0x9)bwi_rf_write(((mac)), ((0x43)), ((bwi_rf_read(((mac)), ((0x43 ))) & (0xfff0)) | (0x9))); |
| 4390 | } |
| 4391 | |
| 4392 | test_lim = 0; |
| 4393 | PHY_WRITE(mac, 0x58, 0)bwi_phy_write((mac), (0x58), (0)); |
| 4394 | for (i = 0; i < 16; ++i) { |
| 4395 | PHY_WRITE(mac, 0x5a, 0x480)bwi_phy_write((mac), (0x5a), (0x480)); |
| 4396 | PHY_WRITE(mac, 0x59, 0xc810)bwi_phy_write((mac), (0x59), (0xc810)); |
| 4397 | |
| 4398 | PHY_WRITE(mac, 0x58, 0xd)bwi_phy_write((mac), (0x58), (0xd)); |
| 4399 | if ((phy->phy_flags & BWI_PHY_F_LINKED0x2) || phy->phy_rev >= 2) { |
| 4400 | phy812_val = bwi_phy812_value(mac, 0x101); |
| 4401 | PHY_WRITE(mac, 0x812, phy812_val)bwi_phy_write((mac), (0x812), (phy812_val)); |
| 4402 | } |
| 4403 | PHY_WRITE(mac, 0x15, 0xafb0)bwi_phy_write((mac), (0x15), (0xafb0)); |
| 4404 | DELAY(10)(*delay_func)(10); |
| 4405 | |
| 4406 | if ((phy->phy_flags & BWI_PHY_F_LINKED0x2) || phy->phy_rev >= 2) { |
| 4407 | phy812_val = bwi_phy812_value(mac, 0x101); |
| 4408 | PHY_WRITE(mac, 0x812, phy812_val)bwi_phy_write((mac), (0x812), (phy812_val)); |
| 4409 | } |
| 4410 | PHY_WRITE(mac, 0x15, 0xefb0)bwi_phy_write((mac), (0x15), (0xefb0)); |
| 4411 | DELAY(10)(*delay_func)(10); |
| 4412 | |
| 4413 | if ((phy->phy_flags & BWI_PHY_F_LINKED0x2) || phy->phy_rev >= 2) { |
| 4414 | phy812_val = bwi_phy812_value(mac, 0x100); |
| 4415 | PHY_WRITE(mac, 0x812, phy812_val)bwi_phy_write((mac), (0x812), (phy812_val)); |
| 4416 | } |
| 4417 | PHY_WRITE(mac, 0x15, 0xfff0)bwi_phy_write((mac), (0x15), (0xfff0)); |
| 4418 | DELAY(20)(*delay_func)(20); |
| 4419 | |
| 4420 | test_lim += PHY_READ(mac, 0x2d)bwi_phy_read((mac), (0x2d)); |
| 4421 | |
| 4422 | PHY_WRITE(mac, 0x58, 0)bwi_phy_write((mac), (0x58), (0)); |
| 4423 | if ((phy->phy_flags & BWI_PHY_F_LINKED0x2) || phy->phy_rev >= 2) { |
| 4424 | phy812_val = bwi_phy812_value(mac, 0x101); |
| 4425 | PHY_WRITE(mac, 0x812, phy812_val)bwi_phy_write((mac), (0x812), (phy812_val)); |
| 4426 | } |
| 4427 | PHY_WRITE(mac, 0x15, 0xafb0)bwi_phy_write((mac), (0x15), (0xafb0)); |
| 4428 | } |
| 4429 | ++test_lim; |
| 4430 | test_lim >>= 9; |
| 4431 | |
| 4432 | DELAY(10)(*delay_func)(10); |
| 4433 | |
| 4434 | test = 0; |
| 4435 | PHY_WRITE(mac, 0x58, 0)bwi_phy_write((mac), (0x58), (0)); |
| 4436 | for (i = 0; i < 16; ++i) { |
| 4437 | int j; |
| 4438 | |
| 4439 | rfr_78 = (bwi_bitswap4(i) << 1) | 0x20; |
| 4440 | RF_WRITE(mac, 0x78, rfr_78)bwi_rf_write((mac), (0x78), (rfr_78)); |
| 4441 | DELAY(10)(*delay_func)(10); |
| 4442 | |
| 4443 | /* NB: This block is slight different than the above one */ |
| 4444 | for (j = 0; j < 16; ++j) { |
| 4445 | PHY_WRITE(mac, 0x5a, 0xd80)bwi_phy_write((mac), (0x5a), (0xd80)); |
| 4446 | PHY_WRITE(mac, 0x59, 0xc810)bwi_phy_write((mac), (0x59), (0xc810)); |
| 4447 | |
| 4448 | PHY_WRITE(mac, 0x58, 0xd)bwi_phy_write((mac), (0x58), (0xd)); |
| 4449 | if ((phy->phy_flags & BWI_PHY_F_LINKED0x2) || |
| 4450 | phy->phy_rev >= 2) { |
| 4451 | phy812_val = bwi_phy812_value(mac, 0x101); |
| 4452 | PHY_WRITE(mac, 0x812, phy812_val)bwi_phy_write((mac), (0x812), (phy812_val)); |
| 4453 | } |
| 4454 | PHY_WRITE(mac, 0x15, 0xafb0)bwi_phy_write((mac), (0x15), (0xafb0)); |
| 4455 | DELAY(10)(*delay_func)(10); |
| 4456 | |
| 4457 | if ((phy->phy_flags & BWI_PHY_F_LINKED0x2) || |
| 4458 | phy->phy_rev >= 2) { |
| 4459 | phy812_val = bwi_phy812_value(mac, 0x101); |
| 4460 | PHY_WRITE(mac, 0x812, phy812_val)bwi_phy_write((mac), (0x812), (phy812_val)); |
| 4461 | } |
| 4462 | PHY_WRITE(mac, 0x15, 0xefb0)bwi_phy_write((mac), (0x15), (0xefb0)); |
| 4463 | DELAY(10)(*delay_func)(10); |
| 4464 | |
| 4465 | if ((phy->phy_flags & BWI_PHY_F_LINKED0x2) || |
| 4466 | phy->phy_rev >= 2) { |
| 4467 | phy812_val = bwi_phy812_value(mac, 0x100); |
| 4468 | PHY_WRITE(mac, 0x812, phy812_val)bwi_phy_write((mac), (0x812), (phy812_val)); |
| 4469 | } |
| 4470 | PHY_WRITE(mac, 0x15, 0xfff0)bwi_phy_write((mac), (0x15), (0xfff0)); |
| 4471 | DELAY(10)(*delay_func)(10); |
| 4472 | |
| 4473 | test += PHY_READ(mac, 0x2d)bwi_phy_read((mac), (0x2d)); |
| 4474 | |
| 4475 | PHY_WRITE(mac, 0x58, 0)bwi_phy_write((mac), (0x58), (0)); |
| 4476 | if ((phy->phy_flags & BWI_PHY_F_LINKED0x2) || |
| 4477 | phy->phy_rev >= 2) { |
| 4478 | phy812_val = bwi_phy812_value(mac, 0x101); |
| 4479 | PHY_WRITE(mac, 0x812, phy812_val)bwi_phy_write((mac), (0x812), (phy812_val)); |
| 4480 | } |
| 4481 | PHY_WRITE(mac, 0x15, 0xafb0)bwi_phy_write((mac), (0x15), (0xafb0)); |
| 4482 | } |
| 4483 | |
| 4484 | ++test; |
| 4485 | test >>= 8; |
| 4486 | |
| 4487 | if (test > test_lim) |
| 4488 | break; |
| 4489 | } |
| 4490 | if (i > 15) |
| 4491 | rf->rf_calib = rfr_78; |
| 4492 | else |
| 4493 | rf->rf_calib = calib; |
| 4494 | 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 | rf->rf_flags |= BWI_RF_F_INITED0x1; |
| 4498 | } |
| 4499 | |
| 4500 | /* |
| 4501 | * Restore trashes registers |
| 4502 | */ |
| 4503 | PHY_WRITE(mac, save_phy_regs_comm[0], save_phy_comm[0])bwi_phy_write((mac), (save_phy_regs_comm[0]), (save_phy_comm[ 0])); |
| 4504 | |
| 4505 | for (i = 0; i < SAVE_RF_MAX; ++i) { |
| 4506 | int pos = (i + 1) % SAVE_RF_MAX; |
| 4507 | |
| 4508 | RF_WRITE(mac, save_rf_regs[pos], save_rf[pos])bwi_rf_write((mac), (save_rf_regs[pos]), (save_rf[pos])); |
| 4509 | } |
| 4510 | for (i = 1; i < SAVE_PHY_COMM_MAX; ++i) |
| 4511 | PHY_WRITE(mac, save_phy_regs_comm[i], save_phy_comm[i])bwi_phy_write((mac), (save_phy_regs_comm[i]), (save_phy_comm[ i])); |
| 4512 | |
| 4513 | CSR_WRITE_2(sc, BWI_BBP_ATTEN, bbp_atten)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03e6 )), ((bbp_atten)))); |
| 4514 | if (phy->phy_version != 0) |
| 4515 | CSR_WRITE_2(sc, BWI_RF_CHAN_EX, rf_chan_ex)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03f4 )), ((rf_chan_ex)))); |
| 4516 | |
| 4517 | PHY_WRITE(mac, 0x35, phyr_35)bwi_phy_write((mac), (0x35), (phyr_35)); |
| 4518 | bwi_rf_workaround(mac, rf->rf_curchan); |
| 4519 | |
| 4520 | if (phy->phy_mode == IEEE80211_MODE_11B) { |
| 4521 | PHY_WRITE(mac, 0x30, phyr_30)bwi_phy_write((mac), (0x30), (phyr_30)); |
| 4522 | CSR_WRITE_2(sc, BWI_BPHY_CTRL, bphy_ctrl)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03ec )), ((bphy_ctrl)))); |
| 4523 | } else if ((phy->phy_flags & BWI_PHY_F_LINKED0x2) || phy->phy_rev >= 2) { |
| 4524 | /* XXX Spec only says when PHY is linked (gmode) */ |
| 4525 | CSR_CLRBITS_2(sc, BWI_RF_ANTDIV, 0x8000)((((sc))->sc_mem_bt)->write_2((((sc))->sc_mem_bh), ( ((0x03e2))), ((((((sc))->sc_mem_bt)->read_2((((sc))-> sc_mem_bh), (((0x03e2))))) & ~(0x8000))))); |
| 4526 | |
| 4527 | for (i = 0; i < SAVE_PHY_11G_MAX; ++i) { |
| 4528 | PHY_WRITE(mac, save_phy_regs_11g[i],bwi_phy_write((mac), (save_phy_regs_11g[i]), (save_phy_11g[i] )) |
| 4529 | save_phy_11g[i])bwi_phy_write((mac), (save_phy_regs_11g[i]), (save_phy_11g[i] )); |
| 4530 | } |
| 4531 | |
| 4532 | PHY_WRITE(mac, 0x80f, phyr_80f)bwi_phy_write((mac), (0x80f), (phyr_80f)); |
| 4533 | PHY_WRITE(mac, 0x810, phyr_810)bwi_phy_write((mac), (0x810), (phyr_810)); |
| 4534 | } |
| 4535 | |
| 4536 | #undef SAVE_PHY_11G_MAX |
| 4537 | #undef SAVE_PHY_COMM_MAX |
| 4538 | #undef SAVE_RF_MAX |
| 4539 | } |
| 4540 | |
| 4541 | uint16_t |
| 4542 | 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 | val = RF_READ(mac, BWI_RFR_BBP_ATTEN)bwi_rf_read((mac), (0x60)); |
| 4554 | idx = __SHIFTOUT(val, BWI_RFR_BBP_ATTEN_CALIB_IDX)(((val) & ((0x0f << 1))) / (((((0x0f << 1)) - 1) & ((0x0f << 1))) ^ ((0x0f << 1)))); |
| 4555 | KASSERT(idx < (int)(sizeof(rf_calibvals) / sizeof(rf_calibvals[0])))((idx < (int)(sizeof(rf_calibvals) / sizeof(rf_calibvals[0 ]))) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c" , 4555, "idx < (int)(sizeof(rf_calibvals) / sizeof(rf_calibvals[0]))" )); |
| 4556 | |
| 4557 | calib = rf_calibvals[idx] << 1; |
| 4558 | if (val & BWI_RFR_BBP_ATTEN_CALIB_BIT(1 << 0)) |
| 4559 | calib |= 0x1; |
| 4560 | calib |= 0x20; |
| 4561 | |
| 4562 | return (calib); |
| 4563 | } |
| 4564 | |
| 4565 | int32_t |
| 4566 | _bwi_adjust_devide(int32_t num, int32_t den) |
| 4567 | { |
| 4568 | if (num < 0) |
| 4569 | return ((num / den)); |
| 4570 | else |
| 4571 | return ((num + den / 2) / den); |
| 4572 | } |
| 4573 | |
| 4574 | /* |
| 4575 | * http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table |
| 4576 | * "calculating table entries" |
| 4577 | */ |
| 4578 | int |
| 4579 | 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 | m1 = _bwi_adjust_devide(16 * pa_params[0] + idx * pa_params[1], 32); |
| 4585 | m2 = imax(_bwi_adjust_devide(32768 + idx * pa_params[2], 256), 1); |
| 4586 | |
| 4587 | #define ITER_MAX 16 |
| 4588 | f = 256; |
| 4589 | for (i = 0; i < ITER_MAX; ++i) { |
| 4590 | int32_t q, d; |
| 4591 | |
| 4592 | q = _bwi_adjust_devide( |
| 4593 | f * 4096 - _bwi_adjust_devide(m2 * f, 16) * f, 2048); |
| 4594 | d = abs(q - f); |
| 4595 | f = q; |
| 4596 | |
| 4597 | if (d < 2) |
| 4598 | break; |
| 4599 | } |
| 4600 | if (i == ITER_MAX) |
| 4601 | return (EINVAL22); |
| 4602 | #undef ITER_MAX |
| 4603 | |
| 4604 | dbm = _bwi_adjust_devide(m1 * f, 8192); |
| 4605 | if (dbm < -127) |
| 4606 | dbm = -127; |
| 4607 | else if (dbm > 128) |
| 4608 | dbm = 128; |
| 4609 | |
| 4610 | *txpwr = dbm; |
| 4611 | |
| 4612 | return (0); |
| 4613 | } |
| 4614 | |
| 4615 | int |
| 4616 | bwi_rf_map_txpower(struct bwi_mac *mac) |
| 4617 | { |
| 4618 | struct bwi_softc *sc = mac->mac_sc; |
| 4619 | struct bwi_rf *rf = &mac->mac_rf; |
| 4620 | struct bwi_phy *phy = &mac->mac_phy; |
| 4621 | uint16_t sprom_ofs, val, mask; |
| 4622 | 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 | val = bwi_read_sprom(sc, BWI_SPROM_MAX_TXPWR0x68); |
| 4629 | if (phy->phy_mode == IEEE80211_MODE_11A) { |
| 4630 | rf->rf_txpower_max = __SHIFTOUT(val,(((val) & (0xff00)) / ((((0xff00) - 1) & (0xff00)) ^ ( 0xff00))) |
| 4631 | BWI_SPROM_MAX_TXPWR_MASK_11A)(((val) & (0xff00)) / ((((0xff00) - 1) & (0xff00)) ^ ( 0xff00))); |
| 4632 | } else { |
| 4633 | rf->rf_txpower_max = __SHIFTOUT(val,(((val) & (0x00ff)) / ((((0x00ff) - 1) & (0x00ff)) ^ ( 0x00ff))) |
| 4634 | BWI_SPROM_MAX_TXPWR_MASK_11BG)(((val) & (0x00ff)) / ((((0x00ff) - 1) & (0x00ff)) ^ ( 0x00ff))); |
| 4635 | |
| 4636 | if ((sc->sc_card_flags & BWI_CARD_F_PA_GPIO9(1 << 1)) && |
| 4637 | phy->phy_mode == IEEE80211_MODE_11G) |
| 4638 | rf->rf_txpower_max -= 3; |
| 4639 | } |
| 4640 | if (rf->rf_txpower_max <= 0) { |
| 4641 | printf("%s: invalid max txpower in sprom\n", |
| 4642 | sc->sc_dev.dv_xname); |
| 4643 | rf->rf_txpower_max = 74; |
| 4644 | } |
| 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 | val = bwi_read_sprom(sc, BWI_SPROM_ANT_GAIN0x74); |
| 4654 | if (phy->phy_mode == IEEE80211_MODE_11A) |
| 4655 | ant_gain = __SHIFTOUT(val, BWI_SPROM_ANT_GAIN_MASK_11A)(((val) & (0x00ff)) / ((((0x00ff) - 1) & (0x00ff)) ^ ( 0x00ff))); |
| 4656 | else |
| 4657 | ant_gain = __SHIFTOUT(val, BWI_SPROM_ANT_GAIN_MASK_11BG)(((val) & (0xff00)) / ((((0xff00) - 1) & (0xff00)) ^ ( 0xff00))); |
| 4658 | 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 | } |
| 4664 | ant_gain *= 4; |
| 4665 | DPRINTF(1, "%s: ant gain %d dBm\n", sc->sc_dev.dv_xname, ant_gain); |
| 4666 | |
| 4667 | 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 | if (rf->rf_txpower_max > reg_txpower_max) |
| 4675 | 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 | if (sc->sc_bbp_id == BWI_BBPID_BCM43010x4301 && |
| 4684 | rf->rf_type != BWI_RF_T_BCM20500x2050) { |
| 4685 | rf->rf_idle_tssi0 = BWI_DEFAULT_IDLE_TSSI52; |
| 4686 | bcopy(bwi_txpower_map_11b, rf->rf_txpower_map0, |
| 4687 | sizeof(rf->rf_txpower_map0)); |
| 4688 | goto back; |
| 4689 | } |
| 4690 | |
| 4691 | #define IS_VALID_PA_PARAM(p) ((p) != 0 && (p) != -1) |
| 4692 | /* |
| 4693 | * Extract PA parameters |
| 4694 | */ |
| 4695 | if (phy->phy_mode == IEEE80211_MODE_11A) |
| 4696 | sprom_ofs = BWI_SPROM_PA_PARAM_11A0x6a; |
| 4697 | else |
| 4698 | sprom_ofs = BWI_SPROM_PA_PARAM_11BG0x5e; |
| 4699 | for (i = 0; i < nitems(pa_params)(sizeof((pa_params)) / sizeof((pa_params)[0])); ++i) |
| 4700 | pa_params[i] = (int16_t)bwi_read_sprom(sc, sprom_ofs + (i * 2)); |
| 4701 | |
| 4702 | for (i = 0; i < nitems(pa_params)(sizeof((pa_params)) / sizeof((pa_params)[0])); ++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 | if (!IS_VALID_PA_PARAM(pa_params[i])) { |
| 4708 | const int8_t *txpower_map; |
| 4709 | |
| 4710 | if (phy->phy_mode == IEEE80211_MODE_11A) { |
| 4711 | printf("%s: no tssi2dbm table for 11a PHY\n", |
| 4712 | sc->sc_dev.dv_xname); |
| 4713 | return (ENXIO6); |
| 4714 | } |
| 4715 | |
| 4716 | 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 | } else { |
| 4721 | txpower_map = bwi_txpower_map_11b; |
| 4722 | } |
| 4723 | |
| 4724 | rf->rf_idle_tssi0 = BWI_DEFAULT_IDLE_TSSI52; |
| 4725 | bcopy(txpower_map, rf->rf_txpower_map0, |
| 4726 | sizeof(rf->rf_txpower_map0)); |
| 4727 | 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 | val = bwi_read_sprom(sc, BWI_SPROM_IDLE_TSSI0x70); |
| 4739 | DPRINTF(1, "%s: sprom idle tssi: 0x%04x\n", sc->sc_dev.dv_xname, val); |
| 4740 | |
| 4741 | if (phy->phy_mode == IEEE80211_MODE_11A) |
| 4742 | mask = BWI_SPROM_IDLE_TSSI_MASK_11A0xff00; |
| 4743 | else |
| 4744 | mask = BWI_SPROM_IDLE_TSSI_MASK_11BG0x00ff; |
| 4745 | |
| 4746 | rf->rf_idle_tssi0 = (int)__SHIFTOUT(val, mask)(((val) & (mask)) / ((((mask) - 1) & (mask)) ^ (mask) )); |
| 4747 | if (!IS_VALID_PA_PARAM(rf->rf_idle_tssi0)) |
| 4748 | 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 | for (i = 0; i < BWI_TSSI_MAX64; ++i) { |
| 4757 | error = bwi_rf_calc_txpower(&rf->rf_txpower_map0[i], i, |
| 4758 | pa_params); |
| 4759 | if (error) { |
| 4760 | printf("%s: bwi_rf_calc_txpower failed\n", |
| 4761 | sc->sc_dev.dv_xname); |
| 4762 | 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 | return (error); |
| 4774 | } |
| 4775 | |
| 4776 | void |
| 4777 | bwi_rf_lo_update_11g(struct bwi_mac *mac) |
| 4778 | { |
| 4779 | struct bwi_softc *sc = mac->mac_sc; |
| 4780 | struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if; |
| 4781 | struct bwi_rf *rf = &mac->mac_rf; |
| 4782 | struct bwi_phy *phy = &mac->mac_phy; |
| 4783 | struct bwi_tpctl *tpctl = &mac->mac_tpctl; |
| 4784 | 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 | orig_chan = rf->rf_curchan; |
| 4795 | bzero(®s, sizeof(regs))__builtin_bzero((®s), (sizeof(regs))); |
| 4796 | |
| 4797 | if (phy->phy_flags & BWI_PHY_F_LINKED0x2) { |
| 4798 | SAVE_PHY_REG(mac, ®s, 429)(®s)->phy_429 = bwi_phy_read(((mac)), (0x429)); |
| 4799 | SAVE_PHY_REG(mac, ®s, 802)(®s)->phy_802 = bwi_phy_read(((mac)), (0x802)); |
| 4800 | |
| 4801 | PHY_WRITE(mac, 0x429, regs.phy_429 & 0x7fff)bwi_phy_write((mac), (0x429), (regs.phy_429 & 0x7fff)); |
| 4802 | PHY_WRITE(mac, 0x802, regs.phy_802 & 0xfffc)bwi_phy_write((mac), (0x802), (regs.phy_802 & 0xfffc)); |
| 4803 | } |
| 4804 | |
| 4805 | ant_div = CSR_READ_2(sc, BWI_RF_ANTDIV)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x03e2 )))); |
| 4806 | CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div | 0x8000)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03e2 )), ((ant_div | 0x8000)))); |
| 4807 | chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x03f4 )))); |
| 4808 | |
| 4809 | SAVE_PHY_REG(mac, ®s, 15)(®s)->phy_15 = bwi_phy_read(((mac)), (0x15)); |
| 4810 | SAVE_PHY_REG(mac, ®s, 2a)(®s)->phy_2a = bwi_phy_read(((mac)), (0x2a)); |
| 4811 | SAVE_PHY_REG(mac, ®s, 35)(®s)->phy_35 = bwi_phy_read(((mac)), (0x35)); |
| 4812 | SAVE_PHY_REG(mac, ®s, 60)(®s)->phy_60 = bwi_phy_read(((mac)), (0x60)); |
| 4813 | SAVE_RF_REG(mac, ®s, 43)(®s)->rf_43 = bwi_rf_read(((mac)), (0x43)); |
| 4814 | SAVE_RF_REG(mac, ®s, 7a)(®s)->rf_7a = bwi_rf_read(((mac)), (0x7a)); |
| 4815 | SAVE_RF_REG(mac, ®s, 52)(®s)->rf_52 = bwi_rf_read(((mac)), (0x52)); |
| 4816 | if (phy->phy_flags & BWI_PHY_F_LINKED0x2) { |
| 4817 | SAVE_PHY_REG(mac, ®s, 811)(®s)->phy_811 = bwi_phy_read(((mac)), (0x811)); |
| 4818 | SAVE_PHY_REG(mac, ®s, 812)(®s)->phy_812 = bwi_phy_read(((mac)), (0x812)); |
| 4819 | SAVE_PHY_REG(mac, ®s, 814)(®s)->phy_814 = bwi_phy_read(((mac)), (0x814)); |
| 4820 | SAVE_PHY_REG(mac, ®s, 815)(®s)->phy_815 = bwi_phy_read(((mac)), (0x815)); |
| 4821 | } |
| 4822 | |
| 4823 | /* Force to channel 6 */ |
| 4824 | bwi_rf_set_chan(mac, 6, 0); |
| 4825 | |
| 4826 | if (phy->phy_flags & BWI_PHY_F_LINKED0x2) { |
| 4827 | PHY_WRITE(mac, 0x429, regs.phy_429 & 0x7fff)bwi_phy_write((mac), (0x429), (regs.phy_429 & 0x7fff)); |
| 4828 | PHY_WRITE(mac, 0x802, regs.phy_802 & 0xfffc)bwi_phy_write((mac), (0x802), (regs.phy_802 & 0xfffc)); |
| 4829 | bwi_mac_dummy_xmit(mac); |
| 4830 | } |
| 4831 | RF_WRITE(mac, 0x43, 0x6)bwi_rf_write((mac), (0x43), (0x6)); |
| 4832 | |
| 4833 | bwi_phy_set_bbp_atten(mac, 2); |
| 4834 | |
| 4835 | CSR_WRITE_2(sc, BWI_RF_CHAN_EX, 0)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03f4 )), ((0)))); |
| 4836 | |
| 4837 | PHY_WRITE(mac, 0x2e, 0x7f)bwi_phy_write((mac), (0x2e), (0x7f)); |
| 4838 | PHY_WRITE(mac, 0x80f, 0x78)bwi_phy_write((mac), (0x80f), (0x78)); |
| 4839 | PHY_WRITE(mac, 0x35, regs.phy_35 & 0xff7f)bwi_phy_write((mac), (0x35), (regs.phy_35 & 0xff7f)); |
| 4840 | RF_WRITE(mac, 0x7a, regs.rf_7a & 0xfff0)bwi_rf_write((mac), (0x7a), (regs.rf_7a & 0xfff0)); |
| 4841 | PHY_WRITE(mac, 0x2b, 0x203)bwi_phy_write((mac), (0x2b), (0x203)); |
| 4842 | PHY_WRITE(mac, 0x2a, 0x8a3)bwi_phy_write((mac), (0x2a), (0x8a3)); |
| 4843 | |
| 4844 | if (phy->phy_flags & BWI_PHY_F_LINKED0x2) { |
| 4845 | PHY_WRITE(mac, 0x814, regs.phy_814 | 0x3)bwi_phy_write((mac), (0x814), (regs.phy_814 | 0x3)); |
| 4846 | PHY_WRITE(mac, 0x815, regs.phy_815 & 0xfffc)bwi_phy_write((mac), (0x815), (regs.phy_815 & 0xfffc)); |
| 4847 | PHY_WRITE(mac, 0x811, 0x1b3)bwi_phy_write((mac), (0x811), (0x1b3)); |
| 4848 | PHY_WRITE(mac, 0x812, 0xb2)bwi_phy_write((mac), (0x812), (0xb2)); |
| 4849 | } |
| 4850 | |
| 4851 | if ((ifp->if_flags & IFF_RUNNING0x40) == 0) |
| 4852 | tpctl->tp_ctrl2 = bwi_rf_get_tp_ctrl2(mac); |
| 4853 | PHY_WRITE(mac, 0x80f, 0x8078)bwi_phy_write((mac), (0x80f), (0x8078)); |
| 4854 | |
| 4855 | /* |
| 4856 | * Measure all RF LO |
| 4857 | */ |
| 4858 | devi_ctrl = _bwi_rf_lo_update_11g(mac, regs.rf_7a); |
| 4859 | |
| 4860 | /* |
| 4861 | * Restore saved RF/PHY registers |
| 4862 | */ |
| 4863 | if (phy->phy_flags & BWI_PHY_F_LINKED0x2) { |
| 4864 | PHY_WRITE(mac, 0x15, 0xe300)bwi_phy_write((mac), (0x15), (0xe300)); |
| 4865 | PHY_WRITE(mac, 0x812, (devi_ctrl << 8) | 0xa0)bwi_phy_write((mac), (0x812), ((devi_ctrl << 8) | 0xa0) ); |
| 4866 | DELAY(5)(*delay_func)(5); |
| 4867 | PHY_WRITE(mac, 0x812, (devi_ctrl << 8) | 0xa2)bwi_phy_write((mac), (0x812), ((devi_ctrl << 8) | 0xa2) ); |
| 4868 | DELAY(2)(*delay_func)(2); |
| 4869 | PHY_WRITE(mac, 0x812, (devi_ctrl << 8) | 0xa3)bwi_phy_write((mac), (0x812), ((devi_ctrl << 8) | 0xa3) ); |
| 4870 | } else |
| 4871 | PHY_WRITE(mac, 0x15, devi_ctrl | 0xefa0)bwi_phy_write((mac), (0x15), (devi_ctrl | 0xefa0)); |
| 4872 | |
| 4873 | if ((ifp->if_flags & IFF_RUNNING0x40) == 0) |
| 4874 | tpctl = NULL((void *)0); |
| 4875 | bwi_rf_lo_adjust(mac, tpctl); |
| 4876 | |
| 4877 | PHY_WRITE(mac, 0x2e, 0x807f)bwi_phy_write((mac), (0x2e), (0x807f)); |
| 4878 | if (phy->phy_flags & BWI_PHY_F_LINKED0x2) |
| 4879 | PHY_WRITE(mac, 0x2f, 0x202)bwi_phy_write((mac), (0x2f), (0x202)); |
| 4880 | else |
| 4881 | PHY_WRITE(mac, 0x2f, 0x101)bwi_phy_write((mac), (0x2f), (0x101)); |
| 4882 | |
| 4883 | CSR_WRITE_2(sc, BWI_RF_CHAN_EX, chan_ex)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03f4 )), ((chan_ex)))); |
| 4884 | |
| 4885 | RESTORE_PHY_REG(mac, ®s, 15)bwi_phy_write(((mac)), (0x15), ((®s)->phy_15)); |
| 4886 | RESTORE_PHY_REG(mac, ®s, 2a)bwi_phy_write(((mac)), (0x2a), ((®s)->phy_2a)); |
| 4887 | RESTORE_PHY_REG(mac, ®s, 35)bwi_phy_write(((mac)), (0x35), ((®s)->phy_35)); |
| 4888 | RESTORE_PHY_REG(mac, ®s, 60)bwi_phy_write(((mac)), (0x60), ((®s)->phy_60)); |
| 4889 | |
| 4890 | RESTORE_RF_REG(mac, ®s, 43)bwi_rf_write(((mac)), (0x43), ((®s)->rf_43)); |
| 4891 | RESTORE_RF_REG(mac, ®s, 7a)bwi_rf_write(((mac)), (0x7a), ((®s)->rf_7a)); |
| 4892 | |
| 4893 | regs.rf_52 &= 0xf0; |
| 4894 | regs.rf_52 |= (RF_READ(mac, 0x52)bwi_rf_read((mac), (0x52)) & 0xf); |
| 4895 | RF_WRITE(mac, 0x52, regs.rf_52)bwi_rf_write((mac), (0x52), (regs.rf_52)); |
| 4896 | |
| 4897 | CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03e2 )), ((ant_div)))); |
| 4898 | |
| 4899 | if (phy->phy_flags & BWI_PHY_F_LINKED0x2) { |
| 4900 | RESTORE_PHY_REG(mac, ®s, 811)bwi_phy_write(((mac)), (0x811), ((®s)->phy_811)); |
| 4901 | RESTORE_PHY_REG(mac, ®s, 812)bwi_phy_write(((mac)), (0x812), ((®s)->phy_812)); |
| 4902 | RESTORE_PHY_REG(mac, ®s, 814)bwi_phy_write(((mac)), (0x814), ((®s)->phy_814)); |
| 4903 | RESTORE_PHY_REG(mac, ®s, 815)bwi_phy_write(((mac)), (0x815), ((®s)->phy_815)); |
| 4904 | RESTORE_PHY_REG(mac, ®s, 429)bwi_phy_write(((mac)), (0x429), ((®s)->phy_429)); |
| 4905 | RESTORE_PHY_REG(mac, ®s, 802)bwi_phy_write(((mac)), (0x802), ((®s)->phy_802)); |
| 4906 | } |
| 4907 | |
| 4908 | bwi_rf_set_chan(mac, orig_chan, 1); |
| 4909 | } |
| 4910 | |
| 4911 | uint32_t |
| 4912 | bwi_rf_lo_devi_measure(struct bwi_mac *mac, uint16_t ctrl) |
| 4913 | { |
| 4914 | struct bwi_phy *phy = &mac->mac_phy; |
| 4915 | uint32_t devi = 0; |
| 4916 | int i; |
| 4917 | |
| 4918 | if (phy->phy_flags & BWI_PHY_F_LINKED0x2) |
| 4919 | ctrl <<= 8; |
| 4920 | |
| 4921 | for (i = 0; i < 8; ++i) { |
| 4922 | if (phy->phy_flags & BWI_PHY_F_LINKED0x2) { |
| 4923 | PHY_WRITE(mac, 0x15, 0xe300)bwi_phy_write((mac), (0x15), (0xe300)); |
| 4924 | PHY_WRITE(mac, 0x812, ctrl | 0xb0)bwi_phy_write((mac), (0x812), (ctrl | 0xb0)); |
| 4925 | DELAY(5)(*delay_func)(5); |
| 4926 | PHY_WRITE(mac, 0x812, ctrl | 0xb2)bwi_phy_write((mac), (0x812), (ctrl | 0xb2)); |
| 4927 | DELAY(2)(*delay_func)(2); |
| 4928 | PHY_WRITE(mac, 0x812, ctrl | 0xb3)bwi_phy_write((mac), (0x812), (ctrl | 0xb3)); |
| 4929 | DELAY(4)(*delay_func)(4); |
| 4930 | PHY_WRITE(mac, 0x15, 0xf300)bwi_phy_write((mac), (0x15), (0xf300)); |
| 4931 | } else { |
| 4932 | PHY_WRITE(mac, 0x15, ctrl | 0xefa0)bwi_phy_write((mac), (0x15), (ctrl | 0xefa0)); |
| 4933 | DELAY(2)(*delay_func)(2); |
| 4934 | PHY_WRITE(mac, 0x15, ctrl | 0xefe0)bwi_phy_write((mac), (0x15), (ctrl | 0xefe0)); |
| 4935 | DELAY(4)(*delay_func)(4); |
| 4936 | PHY_WRITE(mac, 0x15, ctrl | 0xffe0)bwi_phy_write((mac), (0x15), (ctrl | 0xffe0)); |
| 4937 | } |
| 4938 | DELAY(8)(*delay_func)(8); |
| 4939 | devi += PHY_READ(mac, 0x2d)bwi_phy_read((mac), (0x2d)); |
| 4940 | } |
| 4941 | |
| 4942 | return (devi); |
| 4943 | } |
| 4944 | |
| 4945 | uint16_t |
| 4946 | 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 | RF_WRITE(mac, 0x52, 0)bwi_rf_write((mac), (0x52), (0)); |
| 4953 | DELAY(10)(*delay_func)(10); |
| 4954 | devi_min = bwi_rf_lo_devi_measure(mac, 0); |
| 4955 | |
| 4956 | for (i = 0; i < 16; ++i) { |
| 4957 | uint32_t devi; |
| 4958 | |
| 4959 | RF_WRITE(mac, 0x52, i)bwi_rf_write((mac), (0x52), (i)); |
| 4960 | DELAY(10)(*delay_func)(10); |
| 4961 | devi = bwi_rf_lo_devi_measure(mac, 0); |
| 4962 | |
| 4963 | if (devi < devi_min) { |
| 4964 | devi_min = devi; |
| 4965 | tp_ctrl2 = i; |
| 4966 | } |
| 4967 | } |
| 4968 | |
| 4969 | return (tp_ctrl2); |
| 4970 | } |
| 4971 | |
| 4972 | uint8_t |
| 4973 | _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 | struct ifnet *ifp = &mac->mac_sc->sc_ic.ic_ific_ac.ac_if; |
| 4978 | 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 | bzero(&lo_save, sizeof(lo_save))__builtin_bzero((&lo_save), (sizeof(lo_save))); |
| 4990 | for (idx = 0; idx < RF_ATTEN_LISTSZ; ++idx) { |
| 4991 | int init_rf_atten = rf_atten_init_list[idx]; |
| 4992 | int rf_atten = rf_atten_list[idx]; |
| 4993 | int bbp_atten; |
| 4994 | |
| 4995 | for (bbp_atten = 0; bbp_atten < BBP_ATTEN_MAX; ++bbp_atten) { |
| 4996 | uint16_t tp_ctrl2, rf7a; |
| 4997 | |
| 4998 | if ((ifp->if_flags & IFF_RUNNING0x40) == 0) { |
| 4999 | if (idx == 0) { |
| 5000 | bzero(&lo_save, sizeof(lo_save))__builtin_bzero((&lo_save), (sizeof(lo_save))); |
| 5001 | } else if (init_rf_atten < 0) { |
| 5002 | lo = bwi_get_rf_lo(mac, |
| 5003 | rf_atten, 2 * bbp_atten); |
| 5004 | bcopy(lo, &lo_save, sizeof(lo_save)); |
| 5005 | } else { |
| 5006 | lo = bwi_get_rf_lo(mac, |
| 5007 | init_rf_atten, 0); |
| 5008 | 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 | if (init_rf_atten >= 0) { |
| 5019 | int val; |
| 5020 | |
| 5021 | val = rf_atten * 2 + bbp_atten; |
| 5022 | if (val > 14) { |
| 5023 | adj_rf7a = 1; |
| 5024 | if (val > 17) |
| 5025 | devi_ctrl = 1; |
| 5026 | if (val > 19) |
| 5027 | devi_ctrl = 2; |
| 5028 | } |
| 5029 | } |
| 5030 | } else { |
| 5031 | lo = bwi_get_rf_lo(mac, |
| 5032 | rf_atten, 2 * bbp_atten); |
| 5033 | if (!bwi_rf_lo_isused(mac, lo)) |
| 5034 | continue; |
| 5035 | bcopy(lo, &lo_save, sizeof(lo_save)); |
| 5036 | |
| 5037 | devi_ctrl = 3; |
| 5038 | adj_rf7a = 0; |
| 5039 | } |
| 5040 | |
| 5041 | RF_WRITE(mac, BWI_RFR_ATTEN, rf_atten)bwi_rf_write((mac), (0x43), (rf_atten)); |
| 5042 | |
| 5043 | tp_ctrl2 = mac->mac_tpctl.tp_ctrl2; |
| 5044 | if (init_rf_atten < 0) |
| 5045 | tp_ctrl2 |= (3 << 4); |
| 5046 | RF_WRITE(mac, BWI_RFR_TXPWR, tp_ctrl2)bwi_rf_write((mac), (0x52), (tp_ctrl2)); |
| 5047 | |
| 5048 | DELAY(10)(*delay_func)(10); |
| 5049 | |
| 5050 | bwi_phy_set_bbp_atten(mac, bbp_atten * 2); |
| 5051 | |
| 5052 | rf7a = orig_rf7a & 0xfff0; |
| 5053 | if (adj_rf7a) |
| 5054 | rf7a |= 0x8; |
| 5055 | RF_WRITE(mac, 0x7a, rf7a)bwi_rf_write((mac), (0x7a), (rf7a)); |
| 5056 | |
| 5057 | lo = bwi_get_rf_lo(mac, |
| 5058 | rf_lo_measure_order[idx], bbp_atten * 2); |
| 5059 | bwi_rf_lo_measure_11g(mac, &lo_save, lo, devi_ctrl); |
| 5060 | } |
| 5061 | } |
| 5062 | |
| 5063 | return (devi_ctrl); |
| 5064 | |
| 5065 | #undef RF_ATTEN_LISTSZ |
| 5066 | #undef BBP_ATTEN_MAX |
| 5067 | } |
| 5068 | |
| 5069 | void |
| 5070 | 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 | struct bwi_rf_lo lo_min; |
| 5089 | uint32_t devi_min; |
| 5090 | int found, loop_count, adjust_state; |
| 5091 | |
| 5092 | bcopy(src_lo, &lo_min, sizeof(lo_min)); |
| 5093 | RF_LO_WRITE(mac, &lo_min)bwi_rf_lo_write((mac), (&lo_min)); |
| 5094 | devi_min = bwi_rf_lo_devi_measure(mac, devi_ctrl); |
| 5095 | |
| 5096 | loop_count = 12; /* XXX */ |
| 5097 | adjust_state = 0; |
| 5098 | do { |
| 5099 | struct bwi_rf_lo lo_base; |
| 5100 | int i, fin; |
| 5101 | |
| 5102 | found = 0; |
| 5103 | if (adjust_state == 0) { |
| 5104 | i = LO_ADJUST_MIN; |
| 5105 | fin = LO_ADJUST_MAX; |
| 5106 | } else if (adjust_state % 2 == 0) { |
| 5107 | i = adjust_state - 1; |
| 5108 | fin = adjust_state + 1; |
| 5109 | } else { |
| 5110 | i = adjust_state - 2; |
| 5111 | fin = adjust_state + 2; |
| 5112 | } |
| 5113 | |
| 5114 | if (i < LO_ADJUST_MIN) |
| 5115 | i += LO_ADJUST_MAX; |
| 5116 | KASSERT(i <= LO_ADJUST_MAX && i >= LO_ADJUST_MIN)((i <= LO_ADJUST_MAX && i >= LO_ADJUST_MIN) ? ( void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c", 5116, "i <= LO_ADJUST_MAX && i >= LO_ADJUST_MIN" )); |
| 5117 | |
| 5118 | if (fin > LO_ADJUST_MAX) |
| 5119 | fin -= LO_ADJUST_MAX; |
| 5120 | KASSERT(fin <= LO_ADJUST_MAX && fin >= LO_ADJUST_MIN)((fin <= LO_ADJUST_MAX && fin >= LO_ADJUST_MIN) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c" , 5120, "fin <= LO_ADJUST_MAX && fin >= LO_ADJUST_MIN" )); |
| 5121 | |
| 5122 | bcopy(&lo_min, &lo_base, sizeof(lo_base)); |
| 5123 | for (;;) { |
| 5124 | struct bwi_rf_lo lo; |
| 5125 | |
| 5126 | lo.ctrl_hi = lo_base.ctrl_hi + |
| 5127 | rf_lo_adjust[i - 1].ctrl_hi; |
| 5128 | lo.ctrl_lo = lo_base.ctrl_lo + |
| 5129 | rf_lo_adjust[i - 1].ctrl_lo; |
| 5130 | |
| 5131 | if (abs(lo.ctrl_lo) < 9 && abs(lo.ctrl_hi) < 9) { |
| 5132 | uint32_t devi; |
| 5133 | |
| 5134 | RF_LO_WRITE(mac, &lo)bwi_rf_lo_write((mac), (&lo)); |
| 5135 | devi = bwi_rf_lo_devi_measure(mac, devi_ctrl); |
| 5136 | if (devi < devi_min) { |
| 5137 | devi_min = devi; |
| 5138 | adjust_state = i; |
| 5139 | found = 1; |
| 5140 | bcopy(&lo, &lo_min, sizeof(lo_min)); |
| 5141 | } |
| 5142 | } |
| 5143 | if (i == fin) |
| 5144 | break; |
| 5145 | if (i == LO_ADJUST_MAX) |
| 5146 | i = LO_ADJUST_MIN; |
| 5147 | else |
| 5148 | ++i; |
| 5149 | } |
| 5150 | } while (loop_count-- && found); |
| 5151 | |
| 5152 | bcopy(&lo_min, dst_lo, sizeof(*dst_lo)); |
| 5153 | |
| 5154 | #undef LO_ADJUST_MIN |
| 5155 | #undef LO_ADJUST_MAX |
| 5156 | } |
| 5157 | |
| 5158 | void |
| 5159 | bwi_rf_calc_nrssi_slope_11b(struct bwi_mac *mac) |
| 5160 | { |
| 5161 | #define SAVE_RF_MAX 3 |
| 5162 | #define SAVE_PHY_MAX 8 |
| 5163 | struct bwi_softc *sc = mac->mac_sc; |
| 5164 | struct bwi_rf *rf = &mac->mac_rf; |
| 5165 | struct bwi_phy *phy = &mac->mac_phy; |
| 5166 | uint16_t save_rf[SAVE_RF_MAX]; |
| 5167 | 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 | for (i = 0; i < SAVE_RF_MAX; ++i) |
| 5181 | save_rf[i] = RF_READ(mac, save_rf_regs[i])bwi_rf_read((mac), (save_rf_regs[i])); |
| 5182 | for (i = 0; i < SAVE_PHY_MAX; ++i) |
| 5183 | save_phy[i] = PHY_READ(mac, save_phy_regs[i])bwi_phy_read((mac), (save_phy_regs[i])); |
| 5184 | |
| 5185 | ant_div = CSR_READ_2(sc, BWI_RF_ANTDIV)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x03e2 )))); |
| 5186 | bbp_atten = CSR_READ_2(sc, BWI_BBP_ATTEN)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x03e6 )))); |
| 5187 | chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x03f4 )))); |
| 5188 | |
| 5189 | /* |
| 5190 | * Calculate nrssi0 |
| 5191 | */ |
| 5192 | if (phy->phy_rev >= 5) |
| 5193 | RF_CLRBITS(mac, 0x7a, 0xff80)bwi_rf_write(((mac)), ((0x7a)), (bwi_rf_read(((mac)), ((0x7a) )) & ~(0xff80))); |
| 5194 | else |
| 5195 | RF_CLRBITS(mac, 0x7a, 0xfff0)bwi_rf_write(((mac)), ((0x7a)), (bwi_rf_read(((mac)), ((0x7a) )) & ~(0xfff0))); |
| 5196 | PHY_WRITE(mac, 0x30, 0xff)bwi_phy_write((mac), (0x30), (0xff)); |
| 5197 | |
| 5198 | CSR_WRITE_2(sc, BWI_BPHY_CTRL, 0x7f7f)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03ec )), ((0x7f7f)))); |
| 5199 | |
| 5200 | PHY_WRITE(mac, 0x26, 0)bwi_phy_write((mac), (0x26), (0)); |
| 5201 | PHY_SETBITS(mac, 0x15, 0x20)bwi_phy_write(((mac)), ((0x15)), (bwi_phy_read(((mac)), ((0x15 ))) | (0x20))); |
| 5202 | PHY_WRITE(mac, 0x2a, 0x8a3)bwi_phy_write((mac), (0x2a), (0x8a3)); |
| 5203 | RF_SETBITS(mac, 0x7a, 0x80)bwi_rf_write(((mac)), ((0x7a)), (bwi_rf_read(((mac)), ((0x7a) )) | (0x80))); |
| 5204 | |
| 5205 | nrssi[0] = (int16_t)PHY_READ(mac, 0x27)bwi_phy_read((mac), (0x27)); |
| 5206 | |
| 5207 | /* |
| 5208 | * Calculate nrssi1 |
| 5209 | */ |
| 5210 | RF_CLRBITS(mac, 0x7a, 0xff80)bwi_rf_write(((mac)), ((0x7a)), (bwi_rf_read(((mac)), ((0x7a) )) & ~(0xff80))); |
| 5211 | if (phy->phy_version >= 2) |
| 5212 | CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0x40)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03e6 )), ((0x40)))); |
| 5213 | else if (phy->phy_version == 0) |
| 5214 | CSR_WRITE_2(sc, BWI_BBP_ATTEN, 0x122)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03e6 )), ((0x122)))); |
| 5215 | else |
| 5216 | CSR_CLRBITS_2(sc, BWI_RF_CHAN_EX, 0xdfff)((((sc))->sc_mem_bt)->write_2((((sc))->sc_mem_bh), ( ((0x03f4))), ((((((sc))->sc_mem_bt)->read_2((((sc))-> sc_mem_bh), (((0x03f4))))) & ~(0xdfff))))); |
| 5217 | |
| 5218 | PHY_WRITE(mac, 0x20, 0x3f3f)bwi_phy_write((mac), (0x20), (0x3f3f)); |
| 5219 | PHY_WRITE(mac, 0x15, 0xf330)bwi_phy_write((mac), (0x15), (0xf330)); |
| 5220 | |
| 5221 | RF_WRITE(mac, 0x5a, 0x60)bwi_rf_write((mac), (0x5a), (0x60)); |
| 5222 | RF_CLRBITS(mac, 0x43, 0xff0f)bwi_rf_write(((mac)), ((0x43)), (bwi_rf_read(((mac)), ((0x43) )) & ~(0xff0f))); |
| 5223 | |
| 5224 | PHY_WRITE(mac, 0x5a, 0x480)bwi_phy_write((mac), (0x5a), (0x480)); |
| 5225 | PHY_WRITE(mac, 0x59, 0x810)bwi_phy_write((mac), (0x59), (0x810)); |
| 5226 | PHY_WRITE(mac, 0x58, 0xd)bwi_phy_write((mac), (0x58), (0xd)); |
| 5227 | |
| 5228 | DELAY(20)(*delay_func)(20); |
| 5229 | |
| 5230 | nrssi[1] = (int16_t)PHY_READ(mac, 0x27)bwi_phy_read((mac), (0x27)); |
| 5231 | |
| 5232 | /* |
| 5233 | * Restore saved RF/PHY registers |
| 5234 | */ |
| 5235 | PHY_WRITE(mac, save_phy_regs[0], save_phy[0])bwi_phy_write((mac), (save_phy_regs[0]), (save_phy[0])); |
| 5236 | RF_WRITE(mac, save_rf_regs[0], save_rf[0])bwi_rf_write((mac), (save_rf_regs[0]), (save_rf[0])); |
| 5237 | |
| 5238 | CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03e2 )), ((ant_div)))); |
| 5239 | |
| 5240 | for (i = 1; i < 4; ++i) |
| 5241 | PHY_WRITE(mac, save_phy_regs[i], save_phy[i])bwi_phy_write((mac), (save_phy_regs[i]), (save_phy[i])); |
| 5242 | |
| 5243 | bwi_rf_workaround(mac, rf->rf_curchan); |
| 5244 | |
| 5245 | if (phy->phy_version != 0) |
| 5246 | CSR_WRITE_2(sc, BWI_RF_CHAN_EX, chan_ex)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03f4 )), ((chan_ex)))); |
| 5247 | |
| 5248 | for (; i < SAVE_PHY_MAX; ++i) |
| 5249 | PHY_WRITE(mac, save_phy_regs[i], save_phy[i])bwi_phy_write((mac), (save_phy_regs[i]), (save_phy[i])); |
| 5250 | |
| 5251 | for (i = 1; i < SAVE_RF_MAX; ++i) |
| 5252 | RF_WRITE(mac, save_rf_regs[i], save_rf[i])bwi_rf_write((mac), (save_rf_regs[i]), (save_rf[i])); |
| 5253 | |
| 5254 | /* |
| 5255 | * Install calculated narrow RSSI values |
| 5256 | */ |
| 5257 | if (nrssi[0] == nrssi[1]) |
| 5258 | rf->rf_nrssi_slope = 0x10000; |
| 5259 | else |
| 5260 | rf->rf_nrssi_slope = 0x400000 / (nrssi[0] - nrssi[1]); |
| 5261 | if (nrssi[0] <= -4) { |
| 5262 | rf->rf_nrssi[0] = nrssi[0]; |
| 5263 | rf->rf_nrssi[1] = nrssi[1]; |
| 5264 | } |
| 5265 | |
| 5266 | #undef SAVE_RF_MAX |
| 5267 | #undef SAVE_PHY_MAX |
| 5268 | } |
| 5269 | |
| 5270 | void |
| 5271 | 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 | struct bwi_phy *phy = &mac->mac_phy; |
| 5277 | uint16_t save_rf[SAVE_RF_MAX]; |
| 5278 | uint16_t save_phy_comm[SAVE_PHY_COMM_MAX]; |
| 5279 | 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 | for (i = 0; i < SAVE_PHY_COMM_MAX; ++i) |
| 5296 | save_phy_comm[i] = PHY_READ(mac, save_phy_comm_regs[i])bwi_phy_read((mac), (save_phy_comm_regs[i])); |
| 5297 | for (i = 0; i < SAVE_RF_MAX; ++i) |
| 5298 | save_rf[i] = RF_READ(mac, save_rf_regs[i])bwi_rf_read((mac), (save_rf_regs[i])); |
| 5299 | |
| 5300 | PHY_CLRBITS(mac, 0x429, 0x8000)bwi_phy_write(((mac)), ((0x429)), (bwi_phy_read(((mac)), ((0x429 ))) & ~(0x8000))); |
| 5301 | PHY_FILT_SETBITS(mac, 0x1, 0x3fff, 0x4000)bwi_phy_write(((mac)), ((0x1)), ((bwi_phy_read(((mac)), ((0x1 ))) & (0x3fff)) | (0x4000))); |
| 5302 | PHY_SETBITS(mac, 0x811, 0xc)bwi_phy_write(((mac)), ((0x811)), (bwi_phy_read(((mac)), ((0x811 ))) | (0xc))); |
| 5303 | PHY_FILT_SETBITS(mac, 0x812, 0xfff3, 0x4)bwi_phy_write(((mac)), ((0x812)), ((bwi_phy_read(((mac)), ((0x812 ))) & (0xfff3)) | (0x4))); |
| 5304 | PHY_CLRBITS(mac, 0x802, 0x3)bwi_phy_write(((mac)), ((0x802)), (bwi_phy_read(((mac)), ((0x802 ))) & ~(0x3))); |
| 5305 | |
| 5306 | if (phy->phy_rev >= 6) { |
| 5307 | for (i = 0; i < SAVE_PHY6_MAX; ++i) |
| 5308 | save_phy6[i] = PHY_READ(mac, save_phy6_regs[i])bwi_phy_read((mac), (save_phy6_regs[i])); |
| 5309 | |
| 5310 | PHY_WRITE(mac, 0x2e, 0)bwi_phy_write((mac), (0x2e), (0)); |
| 5311 | PHY_WRITE(mac, 0x2f, 0)bwi_phy_write((mac), (0x2f), (0)); |
| 5312 | PHY_WRITE(mac, 0x80f, 0)bwi_phy_write((mac), (0x80f), (0)); |
| 5313 | PHY_WRITE(mac, 0x810, 0)bwi_phy_write((mac), (0x810), (0)); |
| 5314 | PHY_SETBITS(mac, 0x478, 0x100)bwi_phy_write(((mac)), ((0x478)), (bwi_phy_read(((mac)), ((0x478 ))) | (0x100))); |
| 5315 | PHY_SETBITS(mac, 0x801, 0x40)bwi_phy_write(((mac)), ((0x801)), (bwi_phy_read(((mac)), ((0x801 ))) | (0x40))); |
| 5316 | PHY_SETBITS(mac, 0x60, 0x40)bwi_phy_write(((mac)), ((0x60)), (bwi_phy_read(((mac)), ((0x60 ))) | (0x40))); |
| 5317 | PHY_SETBITS(mac, 0x14, 0x200)bwi_phy_write(((mac)), ((0x14)), (bwi_phy_read(((mac)), ((0x14 ))) | (0x200))); |
| 5318 | } |
| 5319 | |
| 5320 | RF_SETBITS(mac, 0x7a, 0x70)bwi_rf_write(((mac)), ((0x7a)), (bwi_rf_read(((mac)), ((0x7a) )) | (0x70))); |
| 5321 | RF_SETBITS(mac, 0x7a, 0x80)bwi_rf_write(((mac)), ((0x7a)), (bwi_rf_read(((mac)), ((0x7a) )) | (0x80))); |
| 5322 | |
| 5323 | DELAY(30)(*delay_func)(30); |
| 5324 | |
| 5325 | nrssi = bwi_nrssi_11g(mac); |
| 5326 | if (nrssi == 31) { |
| 5327 | for (i = 7; i >= 4; --i) { |
| 5328 | RF_WRITE(mac, 0x7b, i)bwi_rf_write((mac), (0x7b), (i)); |
| 5329 | DELAY(20)(*delay_func)(20); |
| 5330 | nrssi = bwi_nrssi_11g(mac); |
| 5331 | if (nrssi < 31 && rf7b == 0xffff) |
| 5332 | rf7b = i; |
| 5333 | } |
| 5334 | if (rf7b == 0xffff) |
| 5335 | rf7b = 4; |
| 5336 | } else { |
| 5337 | struct bwi_gains gains; |
| 5338 | |
| 5339 | RF_CLRBITS(mac, 0x7a, 0xff80)bwi_rf_write(((mac)), ((0x7a)), (bwi_rf_read(((mac)), ((0x7a) )) & ~(0xff80))); |
| 5340 | |
| 5341 | PHY_SETBITS(mac, 0x814, 0x1)bwi_phy_write(((mac)), ((0x814)), (bwi_phy_read(((mac)), ((0x814 ))) | (0x1))); |
| 5342 | PHY_CLRBITS(mac, 0x815, 0x1)bwi_phy_write(((mac)), ((0x815)), (bwi_phy_read(((mac)), ((0x815 ))) & ~(0x1))); |
| 5343 | PHY_SETBITS(mac, 0x811, 0xc)bwi_phy_write(((mac)), ((0x811)), (bwi_phy_read(((mac)), ((0x811 ))) | (0xc))); |
| 5344 | PHY_SETBITS(mac, 0x812, 0xc)bwi_phy_write(((mac)), ((0x812)), (bwi_phy_read(((mac)), ((0x812 ))) | (0xc))); |
| 5345 | PHY_SETBITS(mac, 0x811, 0x30)bwi_phy_write(((mac)), ((0x811)), (bwi_phy_read(((mac)), ((0x811 ))) | (0x30))); |
| 5346 | PHY_SETBITS(mac, 0x812, 0x30)bwi_phy_write(((mac)), ((0x812)), (bwi_phy_read(((mac)), ((0x812 ))) | (0x30))); |
| 5347 | PHY_WRITE(mac, 0x5a, 0x480)bwi_phy_write((mac), (0x5a), (0x480)); |
| 5348 | PHY_WRITE(mac, 0x59, 0x810)bwi_phy_write((mac), (0x59), (0x810)); |
| 5349 | PHY_WRITE(mac, 0x58, 0xd)bwi_phy_write((mac), (0x58), (0xd)); |
| 5350 | if (phy->phy_version == 0) |
| 5351 | PHY_WRITE(mac, 0x3, 0x122)bwi_phy_write((mac), (0x3), (0x122)); |
| 5352 | else |
| 5353 | PHY_SETBITS(mac, 0xa, 0x2000)bwi_phy_write(((mac)), ((0xa)), (bwi_phy_read(((mac)), ((0xa) )) | (0x2000))); |
| 5354 | PHY_SETBITS(mac, 0x814, 0x4)bwi_phy_write(((mac)), ((0x814)), (bwi_phy_read(((mac)), ((0x814 ))) | (0x4))); |
| 5355 | PHY_CLRBITS(mac, 0x815, 0x4)bwi_phy_write(((mac)), ((0x815)), (bwi_phy_read(((mac)), ((0x815 ))) & ~(0x4))); |
| 5356 | PHY_FILT_SETBITS(mac, 0x3, 0xff9f, 0x40)bwi_phy_write(((mac)), ((0x3)), ((bwi_phy_read(((mac)), ((0x3 ))) & (0xff9f)) | (0x40))); |
| 5357 | RF_SETBITS(mac, 0x7a, 0xf)bwi_rf_write(((mac)), ((0x7a)), (bwi_rf_read(((mac)), ((0x7a) )) | (0xf))); |
| 5358 | |
| 5359 | bzero(&gains, sizeof(gains))__builtin_bzero((&gains), (sizeof(gains))); |
| 5360 | gains.tbl_gain1 = 3; |
| 5361 | gains.tbl_gain2 = 0; |
| 5362 | gains.phy_gain = 1; |
| 5363 | bwi_set_gains(mac, &gains); |
| 5364 | |
| 5365 | RF_FILT_SETBITS(mac, 0x43, 0xf0, 0xf)bwi_rf_write(((mac)), ((0x43)), ((bwi_rf_read(((mac)), ((0x43 ))) & (0xf0)) | (0xf))); |
| 5366 | DELAY(30)(*delay_func)(30); |
| 5367 | |
| 5368 | nrssi = bwi_nrssi_11g(mac); |
| 5369 | if (nrssi == -32) { |
| 5370 | for (i = 0; i < 4; ++i) { |
| 5371 | RF_WRITE(mac, 0x7b, i)bwi_rf_write((mac), (0x7b), (i)); |
| 5372 | DELAY(20)(*delay_func)(20); |
| 5373 | nrssi = bwi_nrssi_11g(mac); |
| 5374 | if (nrssi > -31 && rf7b == 0xffff) |
| 5375 | rf7b = i; |
| 5376 | } |
| 5377 | if (rf7b == 0xffff) |
| 5378 | rf7b = 3; |
| 5379 | } else { |
| 5380 | rf7b = 0; |
| 5381 | } |
| 5382 | } |
| 5383 | RF_WRITE(mac, 0x7b, rf7b)bwi_rf_write((mac), (0x7b), (rf7b)); |
| 5384 | |
| 5385 | /* |
| 5386 | * Restore saved RF/PHY registers |
| 5387 | */ |
| 5388 | if (phy->phy_rev >= 6) { |
| 5389 | for (phy6_idx = 0; phy6_idx < 4; ++phy6_idx) { |
| 5390 | PHY_WRITE(mac, save_phy6_regs[phy6_idx],bwi_phy_write((mac), (save_phy6_regs[phy6_idx]), (save_phy6[phy6_idx ])) |
| 5391 | save_phy6[phy6_idx])bwi_phy_write((mac), (save_phy6_regs[phy6_idx]), (save_phy6[phy6_idx ])); |
| 5392 | } |
| 5393 | } |
| 5394 | |
| 5395 | /* Saved PHY registers 0, 1, 2 are handled later */ |
| 5396 | for (i = 3; i < SAVE_PHY_COMM_MAX; ++i) |
| 5397 | PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i])bwi_phy_write((mac), (save_phy_comm_regs[i]), (save_phy_comm[ i])); |
| 5398 | |
| 5399 | for (i = SAVE_RF_MAX - 1; i >= 0; --i) |
| 5400 | RF_WRITE(mac, save_rf_regs[i], save_rf[i])bwi_rf_write((mac), (save_rf_regs[i]), (save_rf[i])); |
| 5401 | |
| 5402 | PHY_SETBITS(mac, 0x802, 0x3)bwi_phy_write(((mac)), ((0x802)), (bwi_phy_read(((mac)), ((0x802 ))) | (0x3))); |
| 5403 | PHY_SETBITS(mac, 0x429, 0x8000)bwi_phy_write(((mac)), ((0x429)), (bwi_phy_read(((mac)), ((0x429 ))) | (0x8000))); |
| 5404 | |
| 5405 | bwi_set_gains(mac, NULL((void *)0)); |
| 5406 | |
| 5407 | if (phy->phy_rev >= 6) { |
| 5408 | for (; phy6_idx < SAVE_PHY6_MAX; ++phy6_idx) { |
| 5409 | PHY_WRITE(mac, save_phy6_regs[phy6_idx],bwi_phy_write((mac), (save_phy6_regs[phy6_idx]), (save_phy6[phy6_idx ])) |
| 5410 | save_phy6[phy6_idx])bwi_phy_write((mac), (save_phy6_regs[phy6_idx]), (save_phy6[phy6_idx ])); |
| 5411 | } |
| 5412 | } |
| 5413 | |
| 5414 | PHY_WRITE(mac, save_phy_comm_regs[0], save_phy_comm[0])bwi_phy_write((mac), (save_phy_comm_regs[0]), (save_phy_comm[ 0])); |
| 5415 | PHY_WRITE(mac, save_phy_comm_regs[2], save_phy_comm[2])bwi_phy_write((mac), (save_phy_comm_regs[2]), (save_phy_comm[ 2])); |
| 5416 | PHY_WRITE(mac, save_phy_comm_regs[1], save_phy_comm[1])bwi_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 | } |
| 5422 | |
| 5423 | void |
| 5424 | 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 | struct bwi_softc *sc = mac->mac_sc; |
| 5430 | struct bwi_phy *phy = &mac->mac_phy; |
| 5431 | struct bwi_rf *rf = &mac->mac_rf; |
| 5432 | uint16_t save_rf[SAVE_RF_MAX]; |
| 5433 | uint16_t save_phy_comm[SAVE_PHY_COMM_MAX]; |
| 5434 | uint16_t save_phy3[SAVE_PHY3_MAX]; |
| 5435 | uint16_t ant_div, bbp_atten, chan_ex; |
| 5436 | 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 | if (rf->rf_rev >= 9) |
| 5450 | return; |
| 5451 | else if (rf->rf_rev == 8) |
| 5452 | bwi_rf_set_nrssi_ofs_11g(mac); |
| 5453 | |
| 5454 | PHY_CLRBITS(mac, 0x429, 0x8000)bwi_phy_write(((mac)), ((0x429)), (bwi_phy_read(((mac)), ((0x429 ))) & ~(0x8000))); |
| 5455 | PHY_CLRBITS(mac, 0x802, 0x3)bwi_phy_write(((mac)), ((0x802)), (bwi_phy_read(((mac)), ((0x802 ))) & ~(0x3))); |
| 5456 | |
| 5457 | /* |
| 5458 | * Save RF/PHY registers for later restoration |
| 5459 | */ |
| 5460 | ant_div = CSR_READ_2(sc, BWI_RF_ANTDIV)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x03e2 )))); |
| 5461 | CSR_SETBITS_2(sc, BWI_RF_ANTDIV, 0x8000)((((sc))->sc_mem_bt)->write_2((((sc))->sc_mem_bh), ( ((0x03e2))), ((((((sc))->sc_mem_bt)->read_2((((sc))-> sc_mem_bh), (((0x03e2))))) | (0x8000))))); |
| 5462 | |
| 5463 | for (i = 0; i < SAVE_RF_MAX; ++i) |
| 5464 | save_rf[i] = RF_READ(mac, save_rf_regs[i])bwi_rf_read((mac), (save_rf_regs[i])); |
| 5465 | for (i = 0; i < SAVE_PHY_COMM_MAX; ++i) |
| 5466 | save_phy_comm[i] = PHY_READ(mac, save_phy_comm_regs[i])bwi_phy_read((mac), (save_phy_comm_regs[i])); |
| 5467 | |
| 5468 | bbp_atten = CSR_READ_2(sc, BWI_BBP_ATTEN)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x03e6 )))); |
| 5469 | chan_ex = CSR_READ_2(sc, BWI_RF_CHAN_EX)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x03f4 )))); |
| 5470 | |
| 5471 | if (phy->phy_rev >= 3) { |
| 5472 | for (i = 0; i < SAVE_PHY3_MAX; ++i) |
| 5473 | save_phy3[i] = PHY_READ(mac, save_phy3_regs[i])bwi_phy_read((mac), (save_phy3_regs[i])); |
| 5474 | |
| 5475 | PHY_WRITE(mac, 0x2e, 0)bwi_phy_write((mac), (0x2e), (0)); |
| 5476 | PHY_WRITE(mac, 0x810, 0)bwi_phy_write((mac), (0x810), (0)); |
| 5477 | |
| 5478 | if (phy->phy_rev == 4 || phy->phy_rev == 6 || |
| 5479 | phy->phy_rev == 7) { |
| 5480 | PHY_SETBITS(mac, 0x478, 0x100)bwi_phy_write(((mac)), ((0x478)), (bwi_phy_read(((mac)), ((0x478 ))) | (0x100))); |
| 5481 | PHY_SETBITS(mac, 0x810, 0x40)bwi_phy_write(((mac)), ((0x810)), (bwi_phy_read(((mac)), ((0x810 ))) | (0x40))); |
| 5482 | } else if (phy->phy_rev == 3 || phy->phy_rev == 5) |
| 5483 | PHY_CLRBITS(mac, 0x810, 0x40)bwi_phy_write(((mac)), ((0x810)), (bwi_phy_read(((mac)), ((0x810 ))) & ~(0x40))); |
| 5484 | |
| 5485 | PHY_SETBITS(mac, 0x60, 0x40)bwi_phy_write(((mac)), ((0x60)), (bwi_phy_read(((mac)), ((0x60 ))) | (0x40))); |
| 5486 | PHY_SETBITS(mac, 0x14, 0x200)bwi_phy_write(((mac)), ((0x14)), (bwi_phy_read(((mac)), ((0x14 ))) | (0x200))); |
| 5487 | } |
| 5488 | |
| 5489 | /* |
| 5490 | * Calculate nrssi0 |
| 5491 | */ |
| 5492 | RF_SETBITS(mac, 0x7a, 0x70)bwi_rf_write(((mac)), ((0x7a)), (bwi_rf_read(((mac)), ((0x7a) )) | (0x70))); |
| 5493 | |
| 5494 | bzero(&gains, sizeof(gains))__builtin_bzero((&gains), (sizeof(gains))); |
| 5495 | gains.tbl_gain1 = 0; |
| 5496 | gains.tbl_gain2 = 8; |
| 5497 | gains.phy_gain = 0; |
| 5498 | bwi_set_gains(mac, &gains); |
| 5499 | |
| 5500 | RF_CLRBITS(mac, 0x7a, 0xff08)bwi_rf_write(((mac)), ((0x7a)), (bwi_rf_read(((mac)), ((0x7a) )) & ~(0xff08))); |
| 5501 | if (phy->phy_rev >= 2) { |
| 5502 | PHY_FILT_SETBITS(mac, 0x811, 0xffcf, 0x30)bwi_phy_write(((mac)), ((0x811)), ((bwi_phy_read(((mac)), ((0x811 ))) & (0xffcf)) | (0x30))); |
| 5503 | PHY_FILT_SETBITS(mac, 0x812, 0xffcf, 0x10)bwi_phy_write(((mac)), ((0x812)), ((bwi_phy_read(((mac)), ((0x812 ))) & (0xffcf)) | (0x10))); |
| 5504 | } |
| 5505 | |
| 5506 | RF_SETBITS(mac, 0x7a, 0x80)bwi_rf_write(((mac)), ((0x7a)), (bwi_rf_read(((mac)), ((0x7a) )) | (0x80))); |
| 5507 | DELAY(20)(*delay_func)(20); |
| 5508 | nrssi[0] = bwi_nrssi_11g(mac); |
| 5509 | |
| 5510 | /* |
| 5511 | * Calculate nrssi1 |
| 5512 | */ |
| 5513 | RF_CLRBITS(mac, 0x7a, 0xff80)bwi_rf_write(((mac)), ((0x7a)), (bwi_rf_read(((mac)), ((0x7a) )) & ~(0xff80))); |
| 5514 | if (phy->phy_version >= 2) |
| 5515 | PHY_FILT_SETBITS(mac, 0x3, 0xff9f, 0x40)bwi_phy_write(((mac)), ((0x3)), ((bwi_phy_read(((mac)), ((0x3 ))) & (0xff9f)) | (0x40))); |
| 5516 | CSR_SETBITS_2(sc, BWI_RF_CHAN_EX, 0x2000)((((sc))->sc_mem_bt)->write_2((((sc))->sc_mem_bh), ( ((0x03f4))), ((((((sc))->sc_mem_bt)->read_2((((sc))-> sc_mem_bh), (((0x03f4))))) | (0x2000))))); |
| 5517 | |
| 5518 | RF_SETBITS(mac, 0x7a, 0xf)bwi_rf_write(((mac)), ((0x7a)), (bwi_rf_read(((mac)), ((0x7a) )) | (0xf))); |
| 5519 | PHY_WRITE(mac, 0x15, 0xf330)bwi_phy_write((mac), (0x15), (0xf330)); |
| 5520 | if (phy->phy_rev >= 2) { |
| 5521 | PHY_FILT_SETBITS(mac, 0x812, 0xffcf, 0x20)bwi_phy_write(((mac)), ((0x812)), ((bwi_phy_read(((mac)), ((0x812 ))) & (0xffcf)) | (0x20))); |
| 5522 | PHY_FILT_SETBITS(mac, 0x811, 0xffcf, 0x20)bwi_phy_write(((mac)), ((0x811)), ((bwi_phy_read(((mac)), ((0x811 ))) & (0xffcf)) | (0x20))); |
| 5523 | } |
| 5524 | |
| 5525 | bzero(&gains, sizeof(gains))__builtin_bzero((&gains), (sizeof(gains))); |
| 5526 | gains.tbl_gain1 = 3; |
| 5527 | gains.tbl_gain2 = 0; |
| 5528 | gains.phy_gain = 1; |
| 5529 | bwi_set_gains(mac, &gains); |
| 5530 | |
| 5531 | if (rf->rf_rev == 8) { |
| 5532 | RF_WRITE(mac, 0x43, 0x1f)bwi_rf_write((mac), (0x43), (0x1f)); |
| 5533 | } else { |
| 5534 | RF_FILT_SETBITS(mac, 0x52, 0xff0f, 0x60)bwi_rf_write(((mac)), ((0x52)), ((bwi_rf_read(((mac)), ((0x52 ))) & (0xff0f)) | (0x60))); |
| 5535 | RF_FILT_SETBITS(mac, 0x43, 0xfff0, 0x9)bwi_rf_write(((mac)), ((0x43)), ((bwi_rf_read(((mac)), ((0x43 ))) & (0xfff0)) | (0x9))); |
| 5536 | } |
| 5537 | PHY_WRITE(mac, 0x5a, 0x480)bwi_phy_write((mac), (0x5a), (0x480)); |
| 5538 | PHY_WRITE(mac, 0x59, 0x810)bwi_phy_write((mac), (0x59), (0x810)); |
| 5539 | PHY_WRITE(mac, 0x58, 0xd)bwi_phy_write((mac), (0x58), (0xd)); |
| 5540 | DELAY(20)(*delay_func)(20); |
| 5541 | |
| 5542 | nrssi[1] = bwi_nrssi_11g(mac); |
| 5543 | |
| 5544 | /* |
| 5545 | * Install calculated narrow RSSI values |
| 5546 | */ |
| 5547 | if (nrssi[1] == nrssi[0]) |
| 5548 | rf->rf_nrssi_slope = 0x10000; |
| 5549 | else |
| 5550 | rf->rf_nrssi_slope = 0x400000 / (nrssi[0] - nrssi[1]); |
| 5551 | if (nrssi[0] >= -4) { |
| 5552 | rf->rf_nrssi[0] = nrssi[1]; |
| 5553 | rf->rf_nrssi[1] = nrssi[0]; |
| 5554 | } |
| 5555 | |
| 5556 | /* |
| 5557 | * Restore saved RF/PHY registers |
| 5558 | */ |
| 5559 | if (phy->phy_rev >= 3) { |
| 5560 | for (phy3_idx = 0; phy3_idx < 4; ++phy3_idx) { |
| 5561 | PHY_WRITE(mac, save_phy3_regs[phy3_idx],bwi_phy_write((mac), (save_phy3_regs[phy3_idx]), (save_phy3[phy3_idx ])) |
| 5562 | save_phy3[phy3_idx])bwi_phy_write((mac), (save_phy3_regs[phy3_idx]), (save_phy3[phy3_idx ])); |
| 5563 | } |
| 5564 | } |
| 5565 | if (phy->phy_rev >= 2) { |
| 5566 | PHY_CLRBITS(mac, 0x812, 0x30)bwi_phy_write(((mac)), ((0x812)), (bwi_phy_read(((mac)), ((0x812 ))) & ~(0x30))); |
| 5567 | PHY_CLRBITS(mac, 0x811, 0x30)bwi_phy_write(((mac)), ((0x811)), (bwi_phy_read(((mac)), ((0x811 ))) & ~(0x30))); |
| 5568 | } |
| 5569 | |
| 5570 | for (i = 0; i < SAVE_RF_MAX; ++i) |
| 5571 | RF_WRITE(mac, save_rf_regs[i], save_rf[i])bwi_rf_write((mac), (save_rf_regs[i]), (save_rf[i])); |
| 5572 | |
| 5573 | CSR_WRITE_2(sc, BWI_RF_ANTDIV, ant_div)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03e2 )), ((ant_div)))); |
| 5574 | CSR_WRITE_2(sc, BWI_BBP_ATTEN, bbp_atten)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03e6 )), ((bbp_atten)))); |
| 5575 | CSR_WRITE_2(sc, BWI_RF_CHAN_EX, chan_ex)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03f4 )), ((chan_ex)))); |
| 5576 | |
| 5577 | for (i = 0; i < SAVE_PHY_COMM_MAX; ++i) |
| 5578 | PHY_WRITE(mac, save_phy_comm_regs[i], save_phy_comm[i])bwi_phy_write((mac), (save_phy_comm_regs[i]), (save_phy_comm[ i])); |
| 5579 | |
| 5580 | bwi_rf_workaround(mac, rf->rf_curchan); |
| 5581 | PHY_SETBITS(mac, 0x802, 0x3)bwi_phy_write(((mac)), ((0x802)), (bwi_phy_read(((mac)), ((0x802 ))) | (0x3))); |
| 5582 | bwi_set_gains(mac, NULL((void *)0)); |
| 5583 | PHY_SETBITS(mac, 0x429, 0x8000)bwi_phy_write(((mac)), ((0x429)), (bwi_phy_read(((mac)), ((0x429 ))) | (0x8000))); |
| 5584 | |
| 5585 | if (phy->phy_rev >= 3) { |
| 5586 | for (; phy3_idx < SAVE_PHY3_MAX; ++phy3_idx) { |
| 5587 | PHY_WRITE(mac, save_phy3_regs[phy3_idx],bwi_phy_write((mac), (save_phy3_regs[phy3_idx]), (save_phy3[phy3_idx ])) |
| 5588 | save_phy3[phy3_idx])bwi_phy_write((mac), (save_phy3_regs[phy3_idx]), (save_phy3[phy3_idx ])); |
| 5589 | } |
| 5590 | } |
| 5591 | |
| 5592 | bwi_rf_init_sw_nrssi_table(mac); |
| 5593 | 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 | } |
| 5599 | |
| 5600 | void |
| 5601 | bwi_rf_init_sw_nrssi_table(struct bwi_mac *mac) |
| 5602 | { |
| 5603 | struct bwi_rf *rf = &mac->mac_rf; |
| 5604 | int d, i; |
| 5605 | |
| 5606 | d = 0x1f - rf->rf_nrssi[0]; |
| 5607 | for (i = 0; i < BWI_NRSSI_TBLSZ64; ++i) { |
| 5608 | int val; |
| 5609 | |
| 5610 | val = (((i - d) * rf->rf_nrssi_slope) / 0x10000) + 0x3a; |
| 5611 | if (val < 0) |
| 5612 | val = 0; |
| 5613 | else if (val > 0x3f) |
| 5614 | val = 0x3f; |
| 5615 | |
| 5616 | rf->rf_nrssi_table[i] = val; |
| 5617 | } |
| 5618 | } |
| 5619 | |
| 5620 | void |
| 5621 | bwi_rf_init_hw_nrssi_table(struct bwi_mac *mac, uint16_t adjust) |
| 5622 | { |
| 5623 | int i; |
| 5624 | |
| 5625 | for (i = 0; i < BWI_NRSSI_TBLSZ64; ++i) { |
| 5626 | int16_t val; |
| 5627 | |
| 5628 | val = bwi_nrssi_read(mac, i); |
| 5629 | |
| 5630 | val -= adjust; |
| 5631 | if (val < -32) |
| 5632 | val = -32; |
| 5633 | else if (val > 31) |
| 5634 | val = 31; |
| 5635 | |
| 5636 | bwi_nrssi_write(mac, i, val); |
| 5637 | } |
| 5638 | } |
| 5639 | |
| 5640 | void |
| 5641 | bwi_rf_set_nrssi_thr_11b(struct bwi_mac *mac) |
| 5642 | { |
| 5643 | struct bwi_rf *rf = &mac->mac_rf; |
| 5644 | int32_t thr; |
| 5645 | |
| 5646 | if (rf->rf_type != BWI_RF_T_BCM20500x2050 || |
| 5647 | (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI(1 << 3)) == 0) |
| 5648 | return; |
| 5649 | |
| 5650 | /* |
| 5651 | * Calculate nrssi threshold |
| 5652 | */ |
| 5653 | if (rf->rf_rev >= 6) { |
| 5654 | thr = (rf->rf_nrssi[1] - rf->rf_nrssi[0]) * 32; |
| 5655 | thr += 20 * (rf->rf_nrssi[0] + 1); |
| 5656 | thr /= 40; |
| 5657 | } else { |
| 5658 | thr = rf->rf_nrssi[1] - 5; |
| 5659 | } |
| 5660 | if (thr < 0) |
| 5661 | thr = 0; |
| 5662 | else if (thr > 0x3e) |
| 5663 | thr = 0x3e; |
| 5664 | |
| 5665 | PHY_READ(mac, BWI_PHYR_NRSSI_THR_11B)bwi_phy_read((mac), (0x020)); /* dummy read */ |
| 5666 | PHY_WRITE(mac, BWI_PHYR_NRSSI_THR_11B, (((uint16_t)thr) << 8) | 0x1c)bwi_phy_write((mac), (0x020), ((((uint16_t)thr) << 8) | 0x1c)); |
| 5667 | |
| 5668 | if (rf->rf_rev >= 6) { |
| 5669 | PHY_WRITE(mac, 0x87, 0xe0d)bwi_phy_write((mac), (0x87), (0xe0d)); |
| 5670 | PHY_WRITE(mac, 0x86, 0xc0b)bwi_phy_write((mac), (0x86), (0xc0b)); |
| 5671 | PHY_WRITE(mac, 0x85, 0xa09)bwi_phy_write((mac), (0x85), (0xa09)); |
| 5672 | PHY_WRITE(mac, 0x84, 0x808)bwi_phy_write((mac), (0x84), (0x808)); |
| 5673 | PHY_WRITE(mac, 0x83, 0x808)bwi_phy_write((mac), (0x83), (0x808)); |
| 5674 | PHY_WRITE(mac, 0x82, 0x604)bwi_phy_write((mac), (0x82), (0x604)); |
| 5675 | PHY_WRITE(mac, 0x81, 0x302)bwi_phy_write((mac), (0x81), (0x302)); |
| 5676 | PHY_WRITE(mac, 0x80, 0x100)bwi_phy_write((mac), (0x80), (0x100)); |
| 5677 | } |
| 5678 | } |
| 5679 | |
| 5680 | int32_t |
| 5681 | _nrssi_threshold(const struct bwi_rf *rf, int32_t val) |
| 5682 | { |
| 5683 | val *= (rf->rf_nrssi[1] - rf->rf_nrssi[0]); |
| 5684 | val += (rf->rf_nrssi[0] << 6); |
| 5685 | if (val < 32) |
| 5686 | val += 31; |
| 5687 | else |
| 5688 | val += 32; |
| 5689 | val >>= 6; |
| 5690 | if (val < -31) |
| 5691 | val = -31; |
| 5692 | else if (val > 31) |
| 5693 | val = 31; |
| 5694 | |
| 5695 | return (val); |
| 5696 | } |
| 5697 | |
| 5698 | void |
| 5699 | 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 | if ((mac->mac_phy.phy_flags & BWI_PHY_F_LINKED0x2) == 0 || |
| 5708 | (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI(1 << 3)) == 0) { |
| 5709 | int16_t nrssi; |
| 5710 | |
| 5711 | nrssi = bwi_nrssi_read(mac, 0x20); |
| 5712 | if (nrssi >= 32) |
| 5713 | nrssi -= 64; |
| 5714 | |
| 5715 | if (nrssi < 3) { |
| 5716 | thr1 = 0x2b; |
| 5717 | thr2 = 0x27; |
| 5718 | } else { |
| 5719 | thr1 = 0x2d; |
| 5720 | thr2 = 0x2b; |
| 5721 | } |
| 5722 | } else { |
| 5723 | /* TODO Interfere mode */ |
| 5724 | thr1 = _nrssi_threshold(&mac->mac_rf, 0x11); |
| 5725 | thr2 = _nrssi_threshold(&mac->mac_rf, 0xe); |
| 5726 | } |
| 5727 | |
| 5728 | #define NRSSI_THR1_MASK 0x003f |
| 5729 | #define NRSSI_THR2_MASK 0x0fc0 |
| 5730 | thr = __SHIFTIN((uint32_t)thr1, NRSSI_THR1_MASK)(((uint32_t)thr1) * ((((NRSSI_THR1_MASK) - 1) & (NRSSI_THR1_MASK )) ^ (NRSSI_THR1_MASK))) | |
| 5731 | __SHIFTIN((uint32_t)thr2, NRSSI_THR2_MASK)(((uint32_t)thr2) * ((((NRSSI_THR2_MASK) - 1) & (NRSSI_THR2_MASK )) ^ (NRSSI_THR2_MASK))); |
| 5732 | PHY_FILT_SETBITS(mac, BWI_PHYR_NRSSI_THR_11G, 0xf000, thr)bwi_phy_write(((mac)), ((0x48a)), ((bwi_phy_read(((mac)), ((0x48a ))) & (0xf000)) | (thr))); |
| 5733 | #undef NRSSI_THR1_MASK |
| 5734 | #undef NRSSI_THR2_MASK |
| 5735 | } |
| 5736 | |
| 5737 | void |
| 5738 | bwi_rf_clear_tssi(struct bwi_mac *mac) |
| 5739 | { |
| 5740 | /* XXX use function pointer */ |
| 5741 | 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)((0x7f) * ((((0x00ff) - 1) & (0x00ff)) ^ (0x00ff))) | |
| 5748 | __SHIFTIN(BWI_INVALID_TSSI, BWI_HI_TSSI_MASK)((0x7f) * ((((0xff00) - 1) & (0xff00)) ^ (0xff00))); |
| 5749 | |
| 5750 | for (i = 0; i < 2; ++i) { |
| 5751 | MOBJ_WRITE_2(mac, BWI_COMM_MOBJ,bwi_memobj_write_2((mac), (0x1), (0x58 + (i * 2)), (val)) |
| 5752 | BWI_COMM_MOBJ_TSSI_DS + (i * 2), val)bwi_memobj_write_2((mac), (0x1), (0x58 + (i * 2)), (val)); |
| 5753 | } |
| 5754 | |
| 5755 | for (i = 0; i < 2; ++i) { |
| 5756 | MOBJ_WRITE_2(mac, BWI_COMM_MOBJ,bwi_memobj_write_2((mac), (0x1), (0x70 + (i * 2)), (val)) |
| 5757 | BWI_COMM_MOBJ_TSSI_OFDM + (i * 2), val)bwi_memobj_write_2((mac), (0x1), (0x70 + (i * 2)), (val)); |
| 5758 | } |
| 5759 | } |
| 5760 | } |
| 5761 | |
| 5762 | void |
| 5763 | bwi_rf_clear_state(struct bwi_rf *rf) |
| 5764 | { |
| 5765 | int i; |
| 5766 | |
| 5767 | rf->rf_flags &= ~BWI_RF_CLEAR_FLAGS(0x1); |
| 5768 | bzero(rf->rf_lo, sizeof(rf->rf_lo))__builtin_bzero((rf->rf_lo), (sizeof(rf->rf_lo))); |
| 5769 | bzero(rf->rf_lo_used, sizeof(rf->rf_lo_used))__builtin_bzero((rf->rf_lo_used), (sizeof(rf->rf_lo_used ))); |
| 5770 | |
| 5771 | rf->rf_nrssi_slope = 0; |
| 5772 | rf->rf_nrssi[0] = BWI_INVALID_NRSSI-1000; |
| 5773 | rf->rf_nrssi[1] = BWI_INVALID_NRSSI-1000; |
| 5774 | |
| 5775 | for (i = 0; i < BWI_NRSSI_TBLSZ64; ++i) |
| 5776 | rf->rf_nrssi_table[i] = i; |
| 5777 | |
| 5778 | rf->rf_lo_gain = 0; |
| 5779 | rf->rf_rx_gain = 0; |
| 5780 | |
| 5781 | bcopy(rf->rf_txpower_map0, rf->rf_txpower_map, |
| 5782 | sizeof(rf->rf_txpower_map)); |
| 5783 | rf->rf_idle_tssi = rf->rf_idle_tssi0; |
| 5784 | } |
| 5785 | |
| 5786 | void |
| 5787 | bwi_rf_on_11a(struct bwi_mac *mac) |
| 5788 | { |
| 5789 | /* TODO: 11A */ |
| 5790 | } |
| 5791 | |
| 5792 | void |
| 5793 | bwi_rf_on_11bg(struct bwi_mac *mac) |
| 5794 | { |
| 5795 | struct bwi_phy *phy = &mac->mac_phy; |
| 5796 | |
| 5797 | PHY_WRITE(mac, 0x15, 0x8000)bwi_phy_write((mac), (0x15), (0x8000)); |
| 5798 | PHY_WRITE(mac, 0x15, 0xcc00)bwi_phy_write((mac), (0x15), (0xcc00)); |
| 5799 | if (phy->phy_flags & BWI_PHY_F_LINKED0x2) |
| 5800 | PHY_WRITE(mac, 0x15, 0xc0)bwi_phy_write((mac), (0x15), (0xc0)); |
| 5801 | else |
| 5802 | PHY_WRITE(mac, 0x15, 0)bwi_phy_write((mac), (0x15), (0)); |
| 5803 | |
| 5804 | bwi_rf_set_chan(mac, 6 /* XXX */, 1); |
| 5805 | } |
| 5806 | |
| 5807 | void |
| 5808 | bwi_rf_set_ant_mode(struct bwi_mac *mac, int ant_mode) |
| 5809 | { |
| 5810 | struct bwi_softc *sc = mac->mac_sc; |
| 5811 | struct bwi_phy *phy = &mac->mac_phy; |
| 5812 | uint16_t val; |
| 5813 | |
| 5814 | KASSERT(ant_mode == BWI_ANT_MODE_0 ||((ant_mode == 0 || ant_mode == 1 || ant_mode == 3) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c", 5816, "ant_mode == BWI_ANT_MODE_0 || ant_mode == BWI_ANT_MODE_1 || ant_mode == BWI_ANT_MODE_AUTO" )) |
| 5815 | ant_mode == BWI_ANT_MODE_1 ||((ant_mode == 0 || ant_mode == 1 || ant_mode == 3) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c", 5816, "ant_mode == BWI_ANT_MODE_0 || ant_mode == BWI_ANT_MODE_1 || ant_mode == BWI_ANT_MODE_AUTO" )) |
| 5816 | ant_mode == BWI_ANT_MODE_AUTO)((ant_mode == 0 || ant_mode == 1 || ant_mode == 3) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c", 5816, "ant_mode == BWI_ANT_MODE_0 || ant_mode == BWI_ANT_MODE_1 || ant_mode == BWI_ANT_MODE_AUTO" )); |
| 5817 | |
| 5818 | HFLAGS_CLRBITS(mac, BWI_HFLAG_AUTO_ANTDIV)bwi_hostflags_write(((mac)), (bwi_hostflags_read(((mac))) | ( 0x1ULL))); |
| 5819 | |
| 5820 | if (phy->phy_mode == IEEE80211_MODE_11B) { |
| 5821 | /* NOTE: v4/v3 conflicts, take v3 */ |
| 5822 | if (mac->mac_revmac_regwin.rw_rev == 2) |
| 5823 | val = BWI_ANT_MODE_AUTO3; |
| 5824 | else |
| 5825 | val = ant_mode; |
| 5826 | val <<= 7; |
| 5827 | PHY_FILT_SETBITS(mac, 0x3e2, 0xfe7f, val)bwi_phy_write(((mac)), ((0x3e2)), ((bwi_phy_read(((mac)), ((0x3e2 ))) & (0xfe7f)) | (val))); |
| 5828 | } else { /* 11a/g */ |
| 5829 | /* XXX reg/value naming */ |
| 5830 | val = ant_mode << 7; |
| 5831 | PHY_FILT_SETBITS(mac, 0x401, 0x7e7f, val)bwi_phy_write(((mac)), ((0x401)), ((bwi_phy_read(((mac)), ((0x401 ))) & (0x7e7f)) | (val))); |
| 5832 | |
| 5833 | if (ant_mode == BWI_ANT_MODE_AUTO3) |
| 5834 | PHY_CLRBITS(mac, 0x42b, 0x100)bwi_phy_write(((mac)), ((0x42b)), (bwi_phy_read(((mac)), ((0x42b ))) & ~(0x100))); |
| 5835 | |
| 5836 | if (phy->phy_mode == IEEE80211_MODE_11A) { |
| 5837 | /* TODO: 11A */ |
| 5838 | } else { /* 11g */ |
| 5839 | if (ant_mode == BWI_ANT_MODE_AUTO3) |
| 5840 | PHY_SETBITS(mac, 0x48c, 0x2000)bwi_phy_write(((mac)), ((0x48c)), (bwi_phy_read(((mac)), ((0x48c ))) | (0x2000))); |
| 5841 | else |
| 5842 | PHY_CLRBITS(mac, 0x48c, 0x2000)bwi_phy_write(((mac)), ((0x48c)), (bwi_phy_read(((mac)), ((0x48c ))) & ~(0x2000))); |
| 5843 | |
| 5844 | if (phy->phy_rev >= 2) { |
| 5845 | PHY_SETBITS(mac, 0x461, 0x10)bwi_phy_write(((mac)), ((0x461)), (bwi_phy_read(((mac)), ((0x461 ))) | (0x10))); |
| 5846 | PHY_FILT_SETBITS(mac, 0x4ad, 0xff00, 0x15)bwi_phy_write(((mac)), ((0x4ad)), ((bwi_phy_read(((mac)), ((0x4ad ))) & (0xff00)) | (0x15))); |
| 5847 | if (phy->phy_rev == 2) { |
| 5848 | PHY_WRITE(mac, 0x427, 0x8)bwi_phy_write((mac), (0x427), (0x8)); |
| 5849 | } else { |
| 5850 | PHY_FILT_SETBITS(mac, 0x427,bwi_phy_write(((mac)), ((0x427)), ((bwi_phy_read(((mac)), ((0x427 ))) & (0xff00)) | (0x8))) |
| 5851 | 0xff00, 0x8)bwi_phy_write(((mac)), ((0x427)), ((bwi_phy_read(((mac)), ((0x427 ))) & (0xff00)) | (0x8))); |
| 5852 | } |
| 5853 | |
| 5854 | if (phy->phy_rev >= 6) |
| 5855 | PHY_WRITE(mac, 0x49b, 0xdc)bwi_phy_write((mac), (0x49b), (0xdc)); |
| 5856 | } |
| 5857 | } |
| 5858 | } |
| 5859 | |
| 5860 | /* XXX v4 set AUTO_ANTDIV unconditionally */ |
| 5861 | if (ant_mode == BWI_ANT_MODE_AUTO3) |
| 5862 | HFLAGS_SETBITS(mac, BWI_HFLAG_AUTO_ANTDIV)bwi_hostflags_write(((mac)), (bwi_hostflags_read(((mac))) & ~(0x1ULL))); |
| 5863 | |
| 5864 | val = ant_mode << 8; |
| 5865 | MOBJ_FILT_SETBITS_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_TX_BEACON,bwi_memobj_write_2(((mac)), ((0x1)), ((0x54)), ((bwi_memobj_read_2 (((mac)), ((0x1)), ((0x54))) & (0xfc3f)) | (val))) |
| 5866 | 0xfc3f, val)bwi_memobj_write_2(((mac)), ((0x1)), ((0x54)), ((bwi_memobj_read_2 (((mac)), ((0x1)), ((0x54))) & (0xfc3f)) | (val))); |
| 5867 | MOBJ_FILT_SETBITS_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_TX_ACK,bwi_memobj_write_2(((mac)), ((0x1)), ((0x22)), ((bwi_memobj_read_2 (((mac)), ((0x1)), ((0x22))) & (0xfc3f)) | (val))) |
| 5868 | 0xfc3f, val)bwi_memobj_write_2(((mac)), ((0x1)), ((0x22)), ((bwi_memobj_read_2 (((mac)), ((0x1)), ((0x22))) & (0xfc3f)) | (val))); |
| 5869 | MOBJ_FILT_SETBITS_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_TX_PROBE_RESP,bwi_memobj_write_2(((mac)), ((0x1)), ((0x188)), ((bwi_memobj_read_2 (((mac)), ((0x1)), ((0x188))) & (0xfc3f)) | (val))) |
| 5870 | 0xfc3f, val)bwi_memobj_write_2(((mac)), ((0x1)), ((0x188)), ((bwi_memobj_read_2 (((mac)), ((0x1)), ((0x188))) & (0xfc3f)) | (val))); |
| 5871 | |
| 5872 | /* XXX what's these */ |
| 5873 | if (phy->phy_mode == IEEE80211_MODE_11B) |
| 5874 | CSR_SETBITS_2(sc, 0x5e, 0x4)((((sc))->sc_mem_bt)->write_2((((sc))->sc_mem_bh), ( ((0x5e))), ((((((sc))->sc_mem_bt)->read_2((((sc))->sc_mem_bh ), (((0x5e))))) | (0x4))))); |
| 5875 | |
| 5876 | CSR_WRITE_4(sc, 0x100, 0x1000000)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x100 )), ((0x1000000)))); |
| 5877 | if (mac->mac_revmac_regwin.rw_rev < 5) |
| 5878 | CSR_WRITE_4(sc, 0x10c, 0x1000000)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x10c )), ((0x1000000)))); |
| 5879 | |
| 5880 | mac->mac_rf.rf_ant_mode = ant_mode; |
| 5881 | } |
| 5882 | |
| 5883 | int |
| 5884 | bwi_rf_get_latest_tssi(struct bwi_mac *mac, int8_t tssi[], uint16_t ofs) |
| 5885 | { |
| 5886 | int i; |
| 5887 | |
| 5888 | for (i = 0; i < 4; ) { |
| 5889 | uint16_t val; |
| 5890 | |
| 5891 | val = MOBJ_READ_2(mac, BWI_COMM_MOBJ, ofs + i)bwi_memobj_read_2((mac), (0x1), (ofs + i)); |
| 5892 | tssi[i++] = (int8_t)__SHIFTOUT(val, BWI_LO_TSSI_MASK)(((val) & (0x00ff)) / ((((0x00ff) - 1) & (0x00ff)) ^ ( 0x00ff))); |
| 5893 | tssi[i++] = (int8_t)__SHIFTOUT(val, BWI_HI_TSSI_MASK)(((val) & (0xff00)) / ((((0xff00) - 1) & (0xff00)) ^ ( 0xff00))); |
| 5894 | } |
| 5895 | |
| 5896 | for (i = 0; i < 4; ++i) { |
| 5897 | if (tssi[i] == BWI_INVALID_TSSI0x7f) |
| 5898 | return (EINVAL22); |
| 5899 | } |
| 5900 | |
| 5901 | return (0); |
| 5902 | } |
| 5903 | |
| 5904 | int |
| 5905 | bwi_rf_tssi2dbm(struct bwi_mac *mac, int8_t tssi, int8_t *txpwr) |
| 5906 | { |
| 5907 | struct bwi_rf *rf = &mac->mac_rf; |
| 5908 | int pwr_idx; |
| 5909 | |
| 5910 | pwr_idx = rf->rf_idle_tssi + (int)tssi - rf->rf_base_tssi; |
| 5911 | #if 0 |
| 5912 | if (pwr_idx < 0 || pwr_idx >= BWI_TSSI_MAX64) |
| 5913 | return EINVAL22; |
| 5914 | #else |
| 5915 | if (pwr_idx < 0) |
| 5916 | pwr_idx = 0; |
| 5917 | else if (pwr_idx >= BWI_TSSI_MAX64) |
| 5918 | pwr_idx = BWI_TSSI_MAX64 - 1; |
| 5919 | #endif |
| 5920 | *txpwr = rf->rf_txpower_map[pwr_idx]; |
| 5921 | |
| 5922 | return (0); |
| 5923 | } |
| 5924 | |
| 5925 | int |
| 5926 | 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 | rssi = hdr->rxh_rssi; |
| 5932 | flags1 = letoh16(hdr->rxh_flags1)((__uint16_t)(hdr->rxh_flags1)); |
| 5933 | flags3 = letoh16(hdr->rxh_flags3)((__uint16_t)(hdr->rxh_flags3)); |
| 5934 | |
| 5935 | #define NEW_BCM2050_RSSI |
| 5936 | #ifdef NEW_BCM2050_RSSI |
| 5937 | if (flags1 & BWI_RXH_F1_OFDM(1 << 0)) { |
| 5938 | if (rssi > 127) |
| 5939 | rssi -= 256; |
| 5940 | if (flags3 & BWI_RXH_F3_BCM2050_RSSI(1 << 10)) |
| 5941 | rssi += 17; |
| 5942 | else |
| 5943 | rssi -= 4; |
| 5944 | return (rssi); |
| 5945 | } |
| 5946 | |
| 5947 | if (mac->mac_sc->sc_card_flags & BWI_CARD_F_SW_NRSSI(1 << 3)) { |
| 5948 | struct bwi_rf *rf = &mac->mac_rf; |
| 5949 | |
| 5950 | if (rssi >= BWI_NRSSI_TBLSZ64) |
| 5951 | rssi = BWI_NRSSI_TBLSZ64 - 1; |
| 5952 | |
| 5953 | rssi = ((31 - (int)rf->rf_nrssi_table[rssi]) * -131) / 128; |
| 5954 | rssi -= 67; |
| 5955 | } else { |
| 5956 | rssi = ((31 - rssi) * -149) / 128; |
| 5957 | rssi -= 68; |
| 5958 | } |
| 5959 | |
| 5960 | if (mac->mac_phy.phy_mode != IEEE80211_MODE_11G) |
| 5961 | return (rssi); |
| 5962 | |
| 5963 | if (flags3 & BWI_RXH_F3_BCM2050_RSSI(1 << 10)) |
| 5964 | rssi += 20; |
| 5965 | |
| 5966 | lna_gain = __SHIFTOUT(letoh16(hdr->rxh_phyinfo),(((((__uint16_t)(hdr->rxh_phyinfo))) & ((3 << 14 ))) / (((((3 << 14)) - 1) & ((3 << 14))) ^ (( 3 << 14)))) |
| 5967 | BWI_RXH_PHYINFO_LNAGAIN)(((((__uint16_t)(hdr->rxh_phyinfo))) & ((3 << 14 ))) / (((((3 << 14)) - 1) & ((3 << 14))) ^ (( 3 << 14)))); |
| 5968 | DPRINTF(3, "lna_gain %d, phyinfo 0x%04x\n", |
| 5969 | lna_gain, letoh16(hdr->rxh_phyinfo)); |
| 5970 | switch (lna_gain) { |
| 5971 | case 0: |
| 5972 | rssi += 27; |
| 5973 | break; |
| 5974 | case 1: |
| 5975 | rssi += 6; |
| 5976 | break; |
| 5977 | case 2: |
| 5978 | rssi += 12; |
| 5979 | 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 | rssi += 5; |
| 5989 | break; |
| 5990 | default: |
| 5991 | 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(1 << 0)) { |
| 5997 | if (rssi > 127) |
| 5998 | rssi -= 256; |
| 5999 | rssi = (rssi * 73) / 64; |
| 6000 | |
| 6001 | if (flags3 & BWI_RXH_F3_BCM2050_RSSI(1 << 10)) |
| 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(1 << 3)) { |
| 6009 | struct bwi_rf *rf = &mac->mac_rf; |
| 6010 | |
| 6011 | if (rssi >= BWI_NRSSI_TBLSZ64) |
| 6012 | rssi = BWI_NRSSI_TBLSZ64 - 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(1 << 10)) |
| 6025 | rssi += 25; |
| 6026 | #endif /* NEW_BCM2050_RSSI */ |
| 6027 | return (rssi); |
| 6028 | } |
| 6029 | |
| 6030 | int |
| 6031 | 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 | rssi = (((int)hdr->rxh_rssi - 11) * 103) / 64; |
| 6037 | |
| 6038 | flags1 = letoh16(hdr->rxh_flags1)((__uint16_t)(hdr->rxh_flags1)); |
| 6039 | if (flags1 & BWI_RXH_F1_BCM2053_RSSI(1 << 14)) |
| 6040 | rssi -= 109; |
| 6041 | else |
| 6042 | rssi -= 83; |
| 6043 | |
| 6044 | return (rssi); |
| 6045 | } |
| 6046 | |
| 6047 | int |
| 6048 | bwi_rf_calc_rssi_bcm2060(struct bwi_mac *mac, const struct bwi_rxbuf_hdr *hdr) |
| 6049 | { |
| 6050 | int rssi; |
| 6051 | |
| 6052 | rssi = hdr->rxh_rssi; |
| 6053 | if (rssi > 127) |
| 6054 | rssi -= 256; |
| 6055 | |
| 6056 | return (rssi); |
| 6057 | } |
| 6058 | |
| 6059 | uint16_t |
| 6060 | bwi_rf_lo_measure_11b(struct bwi_mac *mac) |
| 6061 | { |
| 6062 | uint16_t val; |
| 6063 | int i; |
| 6064 | |
| 6065 | val = 0; |
| 6066 | for (i = 0; i < 10; ++i) { |
| 6067 | PHY_WRITE(mac, 0x15, 0xafa0)bwi_phy_write((mac), (0x15), (0xafa0)); |
| 6068 | DELAY(1)(*delay_func)(1); |
| 6069 | PHY_WRITE(mac, 0x15, 0xefa0)bwi_phy_write((mac), (0x15), (0xefa0)); |
| 6070 | DELAY(10)(*delay_func)(10); |
| 6071 | PHY_WRITE(mac, 0x15, 0xffa0)bwi_phy_write((mac), (0x15), (0xffa0)); |
| 6072 | DELAY(40)(*delay_func)(40); |
| 6073 | |
| 6074 | val += PHY_READ(mac, 0x2c)bwi_phy_read((mac), (0x2c)); |
| 6075 | } |
| 6076 | |
| 6077 | return (val); |
| 6078 | } |
| 6079 | |
| 6080 | void |
| 6081 | bwi_rf_lo_update_11b(struct bwi_mac *mac) |
| 6082 | { |
| 6083 | struct bwi_softc *sc = mac->mac_sc; |
| 6084 | struct bwi_rf *rf = &mac->mac_rf; |
| 6085 | 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 | bzero(®s, sizeof(regs))__builtin_bzero((®s), (sizeof(regs))); |
| 6093 | bphy_ctrl = 0; |
| 6094 | |
| 6095 | /* |
| 6096 | * Save RF/PHY registers for later restoration |
| 6097 | */ |
| 6098 | SAVE_PHY_REG(mac, ®s, 15)(®s)->phy_15 = bwi_phy_read(((mac)), (0x15)); |
| 6099 | rf52 = RF_READ(mac, 0x52)bwi_rf_read((mac), (0x52)) & 0xfff0; |
| 6100 | if (rf->rf_type == BWI_RF_T_BCM20500x2050) { |
| 6101 | SAVE_PHY_REG(mac, ®s, 0a)(®s)->phy_0a = bwi_phy_read(((mac)), (0x0a)); |
| 6102 | SAVE_PHY_REG(mac, ®s, 2a)(®s)->phy_2a = bwi_phy_read(((mac)), (0x2a)); |
| 6103 | SAVE_PHY_REG(mac, ®s, 35)(®s)->phy_35 = bwi_phy_read(((mac)), (0x35)); |
| 6104 | SAVE_PHY_REG(mac, ®s, 03)(®s)->phy_03 = bwi_phy_read(((mac)), (0x03)); |
| 6105 | SAVE_PHY_REG(mac, ®s, 01)(®s)->phy_01 = bwi_phy_read(((mac)), (0x01)); |
| 6106 | SAVE_PHY_REG(mac, ®s, 30)(®s)->phy_30 = bwi_phy_read(((mac)), (0x30)); |
| 6107 | |
| 6108 | SAVE_RF_REG(mac, ®s, 43)(®s)->rf_43 = bwi_rf_read(((mac)), (0x43)); |
| 6109 | SAVE_RF_REG(mac, ®s, 7a)(®s)->rf_7a = bwi_rf_read(((mac)), (0x7a)); |
| 6110 | |
| 6111 | bphy_ctrl = CSR_READ_2(sc, BWI_BPHY_CTRL)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x03ec )))); |
| 6112 | |
| 6113 | SAVE_RF_REG(mac, ®s, 52)(®s)->rf_52 = bwi_rf_read(((mac)), (0x52)); |
| 6114 | regs.rf_52 &= 0xf0; |
| 6115 | |
| 6116 | PHY_WRITE(mac, 0x30, 0xff)bwi_phy_write((mac), (0x30), (0xff)); |
| 6117 | CSR_WRITE_2(sc, BWI_PHY_CTRL, 0x3f3f)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03fc )), ((0x3f3f)))); |
| 6118 | PHY_WRITE(mac, 0x35, regs.phy_35 & 0xff7f)bwi_phy_write((mac), (0x35), (regs.phy_35 & 0xff7f)); |
| 6119 | RF_WRITE(mac, 0x7a, regs.rf_7a & 0xfff0)bwi_rf_write((mac), (0x7a), (regs.rf_7a & 0xfff0)); |
| 6120 | } |
| 6121 | |
| 6122 | PHY_WRITE(mac, 0x15, 0xb000)bwi_phy_write((mac), (0x15), (0xb000)); |
| 6123 | |
| 6124 | if (rf->rf_type == BWI_RF_T_BCM20500x2050) { |
| 6125 | PHY_WRITE(mac, 0x2b, 0x203)bwi_phy_write((mac), (0x2b), (0x203)); |
| 6126 | PHY_WRITE(mac, 0x2a, 0x8a3)bwi_phy_write((mac), (0x2a), (0x8a3)); |
| 6127 | } else { |
| 6128 | PHY_WRITE(mac, 0x2b, 0x1402)bwi_phy_write((mac), (0x2b), (0x1402)); |
| 6129 | } |
| 6130 | |
| 6131 | /* |
| 6132 | * Setup RF signal |
| 6133 | */ |
| 6134 | rf_val = 0; |
| 6135 | min_val = 65535; |
| 6136 | |
| 6137 | for (i = 0; i < 4; ++i) { |
| 6138 | RF_WRITE(mac, 0x52, rf52 | i)bwi_rf_write((mac), (0x52), (rf52 | i)); |
| 6139 | bwi_rf_lo_measure_11b(mac); /* Ignore return value */ |
| 6140 | } |
| 6141 | for (i = 0; i < 10; ++i) { |
| 6142 | RF_WRITE(mac, 0x52, rf52 | i)bwi_rf_write((mac), (0x52), (rf52 | i)); |
| 6143 | |
| 6144 | val = bwi_rf_lo_measure_11b(mac) / 10; |
| 6145 | if (val < min_val) { |
| 6146 | min_val = val; |
| 6147 | rf_val = i; |
| 6148 | } |
| 6149 | } |
| 6150 | RF_WRITE(mac, 0x52, rf52 | rf_val)bwi_rf_write((mac), (0x52), (rf52 | rf_val)); |
| 6151 | |
| 6152 | /* |
| 6153 | * Setup PHY signal |
| 6154 | */ |
| 6155 | phy_val = 0; |
| 6156 | min_val = 65535; |
| 6157 | |
| 6158 | for (i = -4; i < 5; i += 2) { |
| 6159 | int j; |
| 6160 | |
| 6161 | for (j = -4; j < 5; j += 2) { |
| 6162 | uint16_t phy2f; |
| 6163 | |
| 6164 | phy2f = (0x100 * i) + j; |
| 6165 | if (j < 0) |
| 6166 | phy2f += 0x100; |
| 6167 | PHY_WRITE(mac, 0x2f, phy2f)bwi_phy_write((mac), (0x2f), (phy2f)); |
| 6168 | |
| 6169 | val = bwi_rf_lo_measure_11b(mac) / 10; |
| 6170 | if (val < min_val) { |
| 6171 | min_val = val; |
| 6172 | phy_val = phy2f; |
| 6173 | } |
| 6174 | } |
| 6175 | } |
| 6176 | PHY_WRITE(mac, 0x2f, phy_val + 0x101)bwi_phy_write((mac), (0x2f), (phy_val + 0x101)); |
| 6177 | |
| 6178 | /* |
| 6179 | * Restore saved RF/PHY registers |
| 6180 | */ |
| 6181 | if (rf->rf_type == BWI_RF_T_BCM20500x2050) { |
| 6182 | RESTORE_PHY_REG(mac, ®s, 0a)bwi_phy_write(((mac)), (0x0a), ((®s)->phy_0a)); |
| 6183 | RESTORE_PHY_REG(mac, ®s, 2a)bwi_phy_write(((mac)), (0x2a), ((®s)->phy_2a)); |
| 6184 | RESTORE_PHY_REG(mac, ®s, 35)bwi_phy_write(((mac)), (0x35), ((®s)->phy_35)); |
| 6185 | RESTORE_PHY_REG(mac, ®s, 03)bwi_phy_write(((mac)), (0x03), ((®s)->phy_03)); |
| 6186 | RESTORE_PHY_REG(mac, ®s, 01)bwi_phy_write(((mac)), (0x01), ((®s)->phy_01)); |
| 6187 | RESTORE_PHY_REG(mac, ®s, 30)bwi_phy_write(((mac)), (0x30), ((®s)->phy_30)); |
| 6188 | |
| 6189 | RESTORE_RF_REG(mac, ®s, 43)bwi_rf_write(((mac)), (0x43), ((®s)->rf_43)); |
| 6190 | RESTORE_RF_REG(mac, ®s, 7a)bwi_rf_write(((mac)), (0x7a), ((®s)->rf_7a)); |
| 6191 | |
| 6192 | RF_FILT_SETBITS(mac, 0x52, 0xf, regs.rf_52)bwi_rf_write(((mac)), ((0x52)), ((bwi_rf_read(((mac)), ((0x52 ))) & (0xf)) | (regs.rf_52))); |
| 6193 | |
| 6194 | CSR_WRITE_2(sc, BWI_BPHY_CTRL, bphy_ctrl)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x03ec )), ((bphy_ctrl)))); |
| 6195 | } |
| 6196 | RESTORE_PHY_REG(mac, ®s, 15)bwi_phy_write(((mac)), (0x15), ((®s)->phy_15)); |
| 6197 | |
| 6198 | bwi_rf_workaround(mac, rf->rf_curchan); |
| 6199 | } |
| 6200 | |
| 6201 | /* INTERFACE */ |
| 6202 | |
| 6203 | uint16_t |
| 6204 | bwi_read_sprom(struct bwi_softc *sc, uint16_t ofs) |
| 6205 | { |
| 6206 | return (CSR_READ_2(sc, ofs + BWI_SPROM_START)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((ofs + 0x1000))))); |
| 6207 | } |
| 6208 | |
| 6209 | void |
| 6210 | 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 | struct bwi_desc32 *desc = &desc_array[desc_idx]; |
| 6214 | uint32_t ctrl, addr, addr_hi, addr_lo; |
| 6215 | |
| 6216 | if (sc->sc_bus_space == BWI_BUS_SPACE_30BIT && paddr >= 0x40000000) |
| 6217 | panic("bad paddr 0x%lx", (long)paddr); |
| 6218 | |
| 6219 | addr_lo = __SHIFTOUT(paddr, BWI_DESC32_A_ADDR_MASK)(((paddr) & (0x3fffffff)) / ((((0x3fffffff) - 1) & (0x3fffffff )) ^ (0x3fffffff))); |
| 6220 | addr_hi = __SHIFTOUT(paddr, BWI_DESC32_A_FUNC_MASK)(((paddr) & (0xc0000000)) / ((((0xc0000000) - 1) & (0xc0000000 )) ^ (0xc0000000))); |
| 6221 | |
| 6222 | addr = __SHIFTIN(addr_lo, BWI_DESC32_A_ADDR_MASK)((addr_lo) * ((((0x3fffffff) - 1) & (0x3fffffff)) ^ (0x3fffffff ))) | |
| 6223 | __SHIFTIN(BWI_DESC32_A_FUNC_TXRX, BWI_DESC32_A_FUNC_MASK)((0x1) * ((((0xc0000000) - 1) & (0xc0000000)) ^ (0xc0000000 ))); |
| 6224 | |
| 6225 | ctrl = __SHIFTIN(buf_len, BWI_DESC32_C_BUFLEN_MASK)((buf_len) * ((((0x00001fff) - 1) & (0x00001fff)) ^ (0x00001fff ))) | |
| 6226 | __SHIFTIN(addr_hi, BWI_DESC32_C_ADDRHI_MASK)((addr_hi) * ((((0x00030000) - 1) & (0x00030000)) ^ (0x00030000 ))); |
| 6227 | if (desc_idx == ndesc - 1) |
| 6228 | ctrl |= BWI_DESC32_C_EOR(1 << 28); |
| 6229 | if (tx) { |
| 6230 | /* XXX */ |
| 6231 | ctrl |= BWI_DESC32_C_FRAME_START(1U << 31) | |
| 6232 | BWI_DESC32_C_FRAME_END(1 << 30) | |
| 6233 | BWI_DESC32_C_INTR(1 << 29); |
| 6234 | } |
| 6235 | |
| 6236 | desc->addr = htole32(addr)((__uint32_t)(addr)); |
| 6237 | desc->ctrl = htole32(ctrl)((__uint32_t)(ctrl)); |
| 6238 | } |
| 6239 | |
| 6240 | void |
| 6241 | 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 | gpio_in = (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_IN0x000000b0); |
| 6248 | if (gpio_in & BWI_PCIM_GPIO_PWR_ON(1 << 6)) |
| 6249 | goto back; |
| 6250 | |
| 6251 | gpio_out = (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_OUT0x000000b4); |
| 6252 | gpio_en = (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_ENABLE0x000000b8); |
| 6253 | |
| 6254 | gpio_out |= BWI_PCIM_GPIO_PWR_ON(1 << 6); |
| 6255 | gpio_en |= BWI_PCIM_GPIO_PWR_ON(1 << 6); |
| 6256 | if (with_pll) { |
| 6257 | /* Turn off PLL first */ |
| 6258 | gpio_out |= BWI_PCIM_GPIO_PLL_PWR_OFF(1 << 7); |
| 6259 | gpio_en |= BWI_PCIM_GPIO_PLL_PWR_OFF(1 << 7); |
| 6260 | } |
| 6261 | |
| 6262 | (sc->sc_conf_write)(sc, BWI_PCIR_GPIO_OUT0x000000b4, gpio_out); |
| 6263 | (sc->sc_conf_write)(sc, BWI_PCIR_GPIO_ENABLE0x000000b8, gpio_en); |
| 6264 | DELAY(1000)(*delay_func)(1000); |
| 6265 | |
| 6266 | if (with_pll) { |
| 6267 | /* Turn on PLL */ |
| 6268 | gpio_out &= ~BWI_PCIM_GPIO_PLL_PWR_OFF(1 << 7); |
| 6269 | (sc->sc_conf_write)(sc, BWI_PCIR_GPIO_OUT0x000000b4, gpio_out); |
| 6270 | DELAY(5000)(*delay_func)(5000); |
| 6271 | } |
| 6272 | |
| 6273 | back: |
| 6274 | /* Clear "Signaled Target Abort" */ |
| 6275 | status = (sc->sc_conf_read)(sc, PCI_COMMAND_STATUS_REG0x04); |
| 6276 | status &= ~PCI_STATUS_TARGET_TARGET_ABORT0x08000000; |
| 6277 | (sc->sc_conf_write)(sc, PCI_COMMAND_STATUS_REG0x04, status); |
| 6278 | } |
| 6279 | |
| 6280 | int |
| 6281 | 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 | (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_IN0x000000b0); /* dummy read */ |
| 6288 | gpio_out = (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_OUT0x000000b4); |
| 6289 | gpio_en = (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_ENABLE0x000000b8); |
| 6290 | |
| 6291 | gpio_out &= ~BWI_PCIM_GPIO_PWR_ON(1 << 6); |
| 6292 | gpio_en |= BWI_PCIM_GPIO_PWR_ON(1 << 6); |
| 6293 | if (with_pll) { |
| 6294 | gpio_out |= BWI_PCIM_GPIO_PLL_PWR_OFF(1 << 7); |
| 6295 | gpio_en |= BWI_PCIM_GPIO_PLL_PWR_OFF(1 << 7); |
| 6296 | } |
| 6297 | |
| 6298 | (sc->sc_conf_write)(sc, BWI_PCIR_GPIO_OUT0x000000b4, gpio_out); |
| 6299 | (sc->sc_conf_write)(sc, BWI_PCIR_GPIO_ENABLE0x000000b8, gpio_en); |
| 6300 | |
| 6301 | return (0); |
| 6302 | } |
| 6303 | |
| 6304 | int |
| 6305 | bwi_regwin_switch(struct bwi_softc *sc, struct bwi_regwin *rw, |
| 6306 | struct bwi_regwin **old_rw) |
| 6307 | { |
| 6308 | int error; |
| 6309 | |
| 6310 | if (old_rw != NULL((void *)0)) |
| 6311 | *old_rw = NULL((void *)0); |
| 6312 | |
| 6313 | if (!BWI_REGWIN_EXIST(rw)((rw)->rw_flags & 0x1)) |
| 6314 | return (EINVAL22); |
| 6315 | |
| 6316 | if (sc->sc_cur_regwin != rw) { |
| 6317 | error = bwi_regwin_select(sc, rw->rw_id); |
| 6318 | if (error) { |
| 6319 | printf("%s: can't select regwin %d\n", |
| 6320 | sc->sc_dev.dv_xname, rw->rw_id); |
| 6321 | return (error); |
| 6322 | } |
| 6323 | } |
| 6324 | |
| 6325 | if (old_rw != NULL((void *)0)) |
| 6326 | *old_rw = sc->sc_cur_regwin; |
| 6327 | sc->sc_cur_regwin = rw; |
| 6328 | |
| 6329 | return (0); |
| 6330 | } |
| 6331 | |
| 6332 | int |
| 6333 | bwi_regwin_select(struct bwi_softc *sc, int id) |
| 6334 | { |
| 6335 | uint32_t win = BWI_PCIM_REGWIN(id)(((id) * 0x1000) + 0x18000000); |
| 6336 | int i; |
| 6337 | |
| 6338 | #define RETRY_MAX 50 |
| 6339 | for (i = 0; i < RETRY_MAX; ++i) { |
| 6340 | (sc->sc_conf_write)(sc, BWI_PCIR_SEL_REGWIN0x00000080, win); |
| 6341 | if ((sc->sc_conf_read)(sc, BWI_PCIR_SEL_REGWIN0x00000080) == win) |
| 6342 | return (0); |
| 6343 | DELAY(10)(*delay_func)(10); |
| 6344 | } |
| 6345 | #undef RETRY_MAX |
| 6346 | |
| 6347 | return (ENXIO6); |
| 6348 | } |
| 6349 | |
| 6350 | void |
| 6351 | bwi_regwin_info(struct bwi_softc *sc, uint16_t *type, uint8_t *rev) |
| 6352 | { |
| 6353 | uint32_t val; |
| 6354 | |
| 6355 | val = CSR_READ_4(sc, BWI_ID_HI)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000ffc )))); |
| 6356 | *type = BWI_ID_HI_REGWIN_TYPE(val)(((val) & 0x8ff0) >> 4); |
| 6357 | *rev = BWI_ID_HI_REGWIN_REV(val)(((val) & 0xf) | (((val) & 0x7000) >> 8)); |
| 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 | } |
| 6363 | |
| 6364 | void |
| 6365 | bwi_led_attach(struct bwi_softc *sc) |
| 6366 | { |
| 6367 | const uint8_t *led_act = NULL((void *)0); |
| 6368 | uint16_t gpio, val[BWI_LED_MAX4]; |
| 6369 | int i; |
| 6370 | |
| 6371 | for (i = 0; i < nitems(bwi_vendor_led_act)(sizeof((bwi_vendor_led_act)) / sizeof((bwi_vendor_led_act)[0 ])); ++i) { |
| 6372 | if (sc->sc_pci_subvid == bwi_vendor_led_act[i].vid) { |
| 6373 | led_act = bwi_vendor_led_act[i].led_act; |
| 6374 | break; |
| 6375 | } |
| 6376 | } |
| 6377 | if (led_act == NULL((void *)0)) |
| 6378 | led_act = bwi_default_led_act; |
| 6379 | |
| 6380 | gpio = bwi_read_sprom(sc, BWI_SPROM_GPIO010x64); |
| 6381 | val[0] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_0)(((gpio) & (0x00ff)) / ((((0x00ff) - 1) & (0x00ff)) ^ (0x00ff))); |
| 6382 | val[1] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_1)(((gpio) & (0xff00)) / ((((0xff00) - 1) & (0xff00)) ^ (0xff00))); |
| 6383 | |
| 6384 | gpio = bwi_read_sprom(sc, BWI_SPROM_GPIO230x0066); |
| 6385 | val[2] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_2)(((gpio) & (0x00ff)) / ((((0x00ff) - 1) & (0x00ff)) ^ (0x00ff))); |
| 6386 | val[3] = __SHIFTOUT(gpio, BWI_SPROM_GPIO_3)(((gpio) & (0xff00)) / ((((0xff00) - 1) & (0xff00)) ^ (0xff00))); |
| 6387 | |
| 6388 | for (i = 0; i < BWI_LED_MAX4; ++i) { |
| 6389 | struct bwi_led *led = &sc->sc_leds[i]; |
| 6390 | |
| 6391 | if (val[i] == 0xff) { |
| 6392 | led->l_act = led_act[i]; |
| 6393 | } else { |
| 6394 | if (val[i] & BWI_LED_ACT_LOW(1 << 7)) |
| 6395 | led->l_flags |= BWI_LED_F_ACTLOW0x1; |
| 6396 | led->l_act = __SHIFTOUT(val[i], BWI_LED_ACT_MASK)(((val[i]) & (0x7f)) / ((((0x7f) - 1) & (0x7f)) ^ (0x7f ))); |
| 6397 | } |
| 6398 | led->l_mask = (1 << i); |
| 6399 | |
| 6400 | if (led->l_act == BWI_LED_ACT_BLINK_SLOW7 || |
| 6401 | led->l_act == BWI_LED_ACT_BLINK_POLL8 || |
| 6402 | led->l_act == BWI_LED_ACT_BLINK2) { |
| 6403 | led->l_flags |= BWI_LED_F_BLINK0x2; |
| 6404 | if (led->l_act == BWI_LED_ACT_BLINK_POLL8) |
| 6405 | led->l_flags |= BWI_LED_F_POLLABLE0x4; |
| 6406 | else if (led->l_act == BWI_LED_ACT_BLINK_SLOW7) |
| 6407 | led->l_flags |= BWI_LED_F_SLOW0x8; |
| 6408 | |
| 6409 | if (sc->sc_blink_led == NULL((void *)0)) { |
| 6410 | sc->sc_blink_led = led; |
| 6411 | if (led->l_flags & BWI_LED_F_SLOW0x8) |
| 6412 | BWI_LED_SLOWDOWN(sc->sc_led_idle)(sc->sc_led_idle) = (((sc->sc_led_idle) * 3) / 2); |
| 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 | timeout_set(&sc->sc_led_blink_next_ch, bwi_led_blink_next, sc); |
| 6421 | timeout_set(&sc->sc_led_blink_end_ch, bwi_led_blink_end, sc); |
| 6422 | } |
| 6423 | |
| 6424 | uint16_t |
| 6425 | bwi_led_onoff(struct bwi_led *led, uint16_t val, int on) |
| 6426 | { |
| 6427 | if (led->l_flags & BWI_LED_F_ACTLOW0x1) |
| 6428 | on = !on; |
| 6429 | if (on) |
| 6430 | val |= led->l_mask; |
| 6431 | else |
| 6432 | val &= ~led->l_mask; |
| 6433 | |
| 6434 | return (val); |
| 6435 | } |
| 6436 | |
| 6437 | void |
| 6438 | bwi_led_newstate(struct bwi_softc *sc, enum ieee80211_state nstate) |
| 6439 | { |
| 6440 | struct ieee80211com *ic = &sc->sc_ic; |
| 6441 | uint16_t val; |
| 6442 | int i; |
| 6443 | |
| 6444 | if (nstate == IEEE80211_S_INIT) { |
| 6445 | timeout_del(&sc->sc_led_blink_next_ch); |
| 6446 | timeout_del(&sc->sc_led_blink_end_ch); |
| 6447 | sc->sc_led_blinking = 0; |
| 6448 | } |
| 6449 | |
| 6450 | if ((ic->ic_ific_ac.ac_if.if_flags & IFF_RUNNING0x40) == 0) |
| 6451 | return; |
| 6452 | |
| 6453 | val = CSR_READ_2(sc, BWI_MAC_GPIO_CTRL)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x049c )))); |
| 6454 | for (i = 0; i < BWI_LED_MAX4; ++i) { |
| 6455 | struct bwi_led *led = &sc->sc_leds[i]; |
| 6456 | int on; |
| 6457 | |
| 6458 | if (led->l_act == BWI_LED_ACT_UNKN9 || |
| 6459 | led->l_act == BWI_LED_ACT_NULL11) |
| 6460 | continue; |
| 6461 | |
| 6462 | if ((led->l_flags & BWI_LED_F_BLINK0x2) && |
| 6463 | nstate != IEEE80211_S_INIT) |
| 6464 | continue; |
| 6465 | |
| 6466 | switch (led->l_act) { |
| 6467 | case BWI_LED_ACT_ON1: /* Always on */ |
| 6468 | on = 1; |
| 6469 | break; |
| 6470 | case BWI_LED_ACT_OFF0: /* Always off */ |
| 6471 | case BWI_LED_ACT_5GHZ4: /* TODO: 11A */ |
| 6472 | on = 0; |
| 6473 | break; |
| 6474 | default: |
| 6475 | on = 1; |
| 6476 | switch (nstate) { |
| 6477 | case IEEE80211_S_INIT: |
| 6478 | on = 0; |
| 6479 | break; |
| 6480 | case IEEE80211_S_RUN: |
| 6481 | if (led->l_act == BWI_LED_ACT_11G6 && |
| 6482 | ic->ic_curmode != IEEE80211_MODE_11G) |
| 6483 | on = 0; |
| 6484 | break; |
| 6485 | default: |
| 6486 | if (led->l_act == BWI_LED_ACT_ASSOC10) |
| 6487 | on = 0; |
| 6488 | break; |
| 6489 | } |
| 6490 | break; |
| 6491 | } |
| 6492 | |
| 6493 | val = bwi_led_onoff(led, val, on); |
| 6494 | } |
| 6495 | CSR_WRITE_2(sc, BWI_MAC_GPIO_CTRL, val)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x049c )), ((val)))); |
| 6496 | } |
| 6497 | |
| 6498 | void |
| 6499 | bwi_led_event(struct bwi_softc *sc, int event) |
| 6500 | { |
| 6501 | struct bwi_led *led = sc->sc_blink_led; |
| 6502 | int rate; |
| 6503 | |
| 6504 | if (event == BWI_LED_EVENT_POLL0) { |
| 6505 | if ((led->l_flags & BWI_LED_F_POLLABLE0x4) == 0) |
| 6506 | return; |
| 6507 | if (ticks - sc->sc_led_ticks < sc->sc_led_idle) |
| 6508 | return; |
| 6509 | } |
| 6510 | |
| 6511 | sc->sc_led_ticks = ticks; |
| 6512 | if (sc->sc_led_blinking) |
| 6513 | return; |
| 6514 | |
| 6515 | switch (event) { |
| 6516 | case BWI_LED_EVENT_RX2: |
| 6517 | rate = sc->sc_rx_rate; |
| 6518 | break; |
| 6519 | case BWI_LED_EVENT_TX1: |
| 6520 | rate = sc->sc_tx_rate; |
| 6521 | break; |
| 6522 | case BWI_LED_EVENT_POLL0: |
| 6523 | rate = 0; |
| 6524 | break; |
| 6525 | default: |
| 6526 | panic("unknown LED event %d", event); |
| 6527 | break; |
| 6528 | } |
| 6529 | bwi_led_blink_start(sc, bwi_led_duration[rate].on_dur, |
| 6530 | bwi_led_duration[rate].off_dur); |
| 6531 | } |
| 6532 | |
| 6533 | void |
| 6534 | bwi_led_blink_start(struct bwi_softc *sc, int on_dur, int off_dur) |
| 6535 | { |
| 6536 | struct bwi_led *led = sc->sc_blink_led; |
| 6537 | uint16_t val; |
| 6538 | |
| 6539 | val = CSR_READ_2(sc, BWI_MAC_GPIO_CTRL)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x049c )))); |
| 6540 | val = bwi_led_onoff(led, val, 1); |
| 6541 | CSR_WRITE_2(sc, BWI_MAC_GPIO_CTRL, val)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x049c )), ((val)))); |
| 6542 | |
| 6543 | if (led->l_flags & BWI_LED_F_SLOW0x8) { |
| 6544 | BWI_LED_SLOWDOWN(on_dur)(on_dur) = (((on_dur) * 3) / 2); |
| 6545 | BWI_LED_SLOWDOWN(off_dur)(off_dur) = (((off_dur) * 3) / 2); |
| 6546 | } |
| 6547 | |
| 6548 | sc->sc_led_blinking = 1; |
| 6549 | sc->sc_led_blink_offdur = off_dur; |
| 6550 | |
| 6551 | timeout_add(&sc->sc_led_blink_next_ch, on_dur); |
| 6552 | } |
| 6553 | |
| 6554 | void |
| 6555 | bwi_led_blink_next(void *xsc) |
| 6556 | { |
| 6557 | struct bwi_softc *sc = xsc; |
| 6558 | uint16_t val; |
| 6559 | |
| 6560 | val = CSR_READ_2(sc, BWI_MAC_GPIO_CTRL)(((sc)->sc_mem_bt)->read_2(((sc)->sc_mem_bh), ((0x049c )))); |
| 6561 | val = bwi_led_onoff(sc->sc_blink_led, val, 0); |
| 6562 | CSR_WRITE_2(sc, BWI_MAC_GPIO_CTRL, val)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x049c )), ((val)))); |
| 6563 | |
| 6564 | timeout_add(&sc->sc_led_blink_end_ch, sc->sc_led_blink_offdur); |
| 6565 | } |
| 6566 | |
| 6567 | void |
| 6568 | bwi_led_blink_end(void *xsc) |
| 6569 | { |
| 6570 | struct bwi_softc *sc = xsc; |
| 6571 | |
| 6572 | sc->sc_led_blinking = 0; |
| 6573 | } |
| 6574 | |
| 6575 | int |
| 6576 | bwi_bbp_attach(struct bwi_softc *sc) |
| 6577 | { |
| 6578 | uint16_t bbp_id, rw_type; |
| 6579 | 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 | error = bwi_regwin_select(sc, 0); |
| 6588 | if (error) { |
| 6589 | printf("%s: can't select regwin 0\n", sc->sc_dev.dv_xname); |
| 6590 | return (error); |
| 6591 | } |
| 6592 | bwi_regwin_info(sc, &rw_type, &rw_rev); |
| 6593 | |
| 6594 | /* |
| 6595 | * Find out BBP id |
| 6596 | */ |
| 6597 | bbp_id = 0; |
| 6598 | info = 0; |
| 6599 | if (rw_type == BWI_REGWIN_T_COM0x800) { |
| 6600 | info = CSR_READ_4(sc, BWI_INFO)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000000 )))); |
| 6601 | bbp_id = __SHIFTOUT(info, BWI_INFO_BBPID_MASK)(((info) & (0x0000ffff)) / ((((0x0000ffff) - 1) & (0x0000ffff )) ^ (0x0000ffff))); |
| 6602 | |
| 6603 | BWI_CREATE_REGWIN(&sc->sc_com_regwin, 0, rw_type, rw_rev)do { (&sc->sc_com_regwin)->rw_flags = 0x1; (&sc ->sc_com_regwin)->rw_type = (rw_type); (&sc->sc_com_regwin )->rw_id = (0); (&sc->sc_com_regwin)->rw_rev = ( rw_rev); } while (0); |
| 6604 | |
| 6605 | sc->sc_cap = CSR_READ_4(sc, BWI_CAPABILITY)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000004 )))); |
| 6606 | } else { |
| 6607 | uint16_t did = sc->sc_pci_did; |
| 6608 | uint8_t revid = sc->sc_pci_revid; |
| 6609 | |
| 6610 | for (i = 0; i < nitems(bwi_bbpid_map)(sizeof((bwi_bbpid_map)) / sizeof((bwi_bbpid_map)[0])); ++i) { |
| 6611 | if (did >= bwi_bbpid_map[i].did_min && |
| 6612 | did <= bwi_bbpid_map[i].did_max) { |
| 6613 | bbp_id = bwi_bbpid_map[i].bbp_id; |
| 6614 | break; |
| 6615 | } |
| 6616 | } |
| 6617 | if (bbp_id == 0) { |
| 6618 | printf("%s: no BBP id for device id 0x%04x\n", |
| 6619 | sc->sc_dev.dv_xname, did); |
| 6620 | return (ENXIO6); |
| 6621 | } |
| 6622 | |
| 6623 | info = __SHIFTIN(revid, BWI_INFO_BBPREV_MASK)((revid) * ((((0x000f0000) - 1) & (0x000f0000)) ^ (0x000f0000 ))) | |
| 6624 | __SHIFTIN(0, BWI_INFO_BBPPKG_MASK)((0) * ((((0x00f00000) - 1) & (0x00f00000)) ^ (0x00f00000 ))); |
| 6625 | } |
| 6626 | |
| 6627 | /* |
| 6628 | * Find out number of regwins |
| 6629 | */ |
| 6630 | nregwin = 0; |
| 6631 | if (rw_type == BWI_REGWIN_T_COM0x800 && rw_rev >= 4) { |
| 6632 | nregwin = __SHIFTOUT(info, BWI_INFO_NREGWIN_MASK)(((info) & (0x0f000000)) / ((((0x0f000000) - 1) & (0x0f000000 )) ^ (0x0f000000))); |
| 6633 | } else { |
| 6634 | for (i = 0; i < nitems(bwi_regwin_count)(sizeof((bwi_regwin_count)) / sizeof((bwi_regwin_count)[0])); ++i) { |
| 6635 | if (bwi_regwin_count[i].bbp_id == bbp_id) { |
| 6636 | nregwin = bwi_regwin_count[i].nregwin; |
| 6637 | break; |
| 6638 | } |
| 6639 | } |
| 6640 | if (nregwin == 0) { |
| 6641 | printf("%s: no number of win for BBP id 0x%04x\n", |
| 6642 | sc->sc_dev.dv_xname, bbp_id); |
| 6643 | return (ENXIO6); |
| 6644 | } |
| 6645 | } |
| 6646 | |
| 6647 | /* Record BBP id/rev for later using */ |
| 6648 | sc->sc_bbp_id = bbp_id; |
| 6649 | sc->sc_bbp_rev = __SHIFTOUT(info, BWI_INFO_BBPREV_MASK)(((info) & (0x000f0000)) / ((((0x000f0000) - 1) & (0x000f0000 )) ^ (0x000f0000))); |
| 6650 | sc->sc_bbp_pkg = __SHIFTOUT(info, BWI_INFO_BBPPKG_MASK)(((info) & (0x00f00000)) / ((((0x00f00000) - 1) & (0x00f00000 )) ^ (0x00f00000))); |
| 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 | i = BWI_REGWIN_EXIST(&sc->sc_com_regwin)((&sc->sc_com_regwin)->rw_flags & 0x1) ? 1 : 0; |
| 6662 | |
| 6663 | for (; i < nregwin; ++i) { |
| 6664 | /* |
| 6665 | * Get regwin information |
| 6666 | */ |
| 6667 | error = bwi_regwin_select(sc, i); |
| 6668 | if (error) { |
| 6669 | printf("%s: can't select regwin %d\n", |
| 6670 | sc->sc_dev.dv_xname, i); |
| 6671 | return (error); |
| 6672 | } |
| 6673 | 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 | if (rw_type == BWI_REGWIN_T_BUSPCI0x804 || |
| 6682 | rw_type == BWI_REGWIN_T_BUSPCIE0x820) { |
| 6683 | if (BWI_REGWIN_EXIST(&sc->sc_bus_regwin)((&sc->sc_bus_regwin)->rw_flags & 0x1)) { |
| 6684 | printf("%s: bus regwin already exists\n", |
| 6685 | sc->sc_dev.dv_xname); |
| 6686 | } else { |
| 6687 | BWI_CREATE_REGWIN(&sc->sc_bus_regwin, i,do { (&sc->sc_bus_regwin)->rw_flags = 0x1; (&sc ->sc_bus_regwin)->rw_type = (rw_type); (&sc->sc_bus_regwin )->rw_id = (i); (&sc->sc_bus_regwin)->rw_rev = ( rw_rev); } while (0) |
| 6688 | rw_type, rw_rev)do { (&sc->sc_bus_regwin)->rw_flags = 0x1; (&sc ->sc_bus_regwin)->rw_type = (rw_type); (&sc->sc_bus_regwin )->rw_id = (i); (&sc->sc_bus_regwin)->rw_rev = ( rw_rev); } while (0); |
| 6689 | } |
| 6690 | } else if (rw_type == BWI_REGWIN_T_MAC0x812) { |
| 6691 | /* XXX ignore return value */ |
| 6692 | bwi_mac_attach(sc, i, rw_rev); |
| 6693 | } |
| 6694 | } |
| 6695 | |
| 6696 | /* At least one MAC should exist */ |
| 6697 | if (!BWI_REGWIN_EXIST(&sc->sc_mac[0].mac_regwin)((&sc->sc_mac[0].mac_regwin)->rw_flags & 0x1)) { |
| 6698 | printf("%s: no MAC was found\n", sc->sc_dev.dv_xname); |
| 6699 | return (ENXIO6); |
| 6700 | } |
| 6701 | KASSERT(sc->sc_nmac > 0)((sc->sc_nmac > 0) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c" , 6701, "sc->sc_nmac > 0")); |
| 6702 | |
| 6703 | /* Bus regwin must exist */ |
| 6704 | if (!BWI_REGWIN_EXIST(&sc->sc_bus_regwin)((&sc->sc_bus_regwin)->rw_flags & 0x1)) { |
| 6705 | printf("%s: no bus regwin was found\n", sc->sc_dev.dv_xname); |
| 6706 | return (ENXIO6); |
| 6707 | } |
| 6708 | |
| 6709 | /* Start with first MAC */ |
| 6710 | error = bwi_regwin_switch(sc, &sc->sc_mac[0].mac_regwin, NULL((void *)0)); |
| 6711 | if (error) |
| 6712 | return (error); |
| 6713 | |
| 6714 | return (0); |
| 6715 | } |
| 6716 | |
| 6717 | int |
| 6718 | bwi_bus_init(struct bwi_softc *sc, struct bwi_mac *mac) |
| 6719 | { |
| 6720 | struct bwi_regwin *old, *bus; |
| 6721 | uint32_t val; |
| 6722 | int error; |
| 6723 | |
| 6724 | bus = &sc->sc_bus_regwin; |
| 6725 | KASSERT(sc->sc_cur_regwin == &mac->mac_regwin)((sc->sc_cur_regwin == &mac->mac_regwin) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c", 6725, "sc->sc_cur_regwin == &mac->mac_regwin" )); |
| 6726 | |
| 6727 | /* |
| 6728 | * Tell bus to generate requested interrupts |
| 6729 | */ |
| 6730 | if (bus->rw_rev < 6 && bus->rw_type == BWI_REGWIN_T_BUSPCI0x804) { |
| 6731 | /* |
| 6732 | * NOTE: Read BWI_FLAGS from MAC regwin |
| 6733 | */ |
| 6734 | val = CSR_READ_4(sc, BWI_FLAGS)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000f18 )))); |
| 6735 | |
| 6736 | error = bwi_regwin_switch(sc, bus, &old); |
| 6737 | if (error) |
| 6738 | return (error); |
| 6739 | |
| 6740 | CSR_SETBITS_4(sc, BWI_INTRVEC, (val & BWI_FLAGS_INTR_MASK))((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x00000f94))), ((((((sc))->sc_mem_bt)->read_4((((sc)) ->sc_mem_bh), (((0x00000f94))))) | ((val & 0x0000003f) ))))); |
| 6741 | } else { |
| 6742 | uint32_t mac_mask; |
| 6743 | |
| 6744 | mac_mask = 1 << mac->mac_idmac_regwin.rw_id; |
| 6745 | |
| 6746 | error = bwi_regwin_switch(sc, bus, &old); |
| 6747 | if (error) |
| 6748 | return (error); |
| 6749 | |
| 6750 | val = (sc->sc_conf_read)(sc, BWI_PCIR_INTCTL0x00000094); |
| 6751 | val |= mac_mask << 8; |
| 6752 | (sc->sc_conf_write)(sc, BWI_PCIR_INTCTL0x00000094, val); |
| 6753 | } |
| 6754 | |
| 6755 | if (sc->sc_flags & BWI_F_BUS_INITED0x1) |
| 6756 | goto back; |
| 6757 | |
| 6758 | if (bus->rw_type == BWI_REGWIN_T_BUSPCI0x804) { |
| 6759 | /* |
| 6760 | * Enable prefetch and burst |
| 6761 | */ |
| 6762 | CSR_SETBITS_4(sc, BWI_BUS_CONFIG,((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x00000108))), ((((((sc))->sc_mem_bt)->read_4((((sc)) ->sc_mem_bh), (((0x00000108))))) | ((1 << 2) | (1 << 3)))))) |
| 6763 | BWI_BUS_CONFIG_PREFETCH | BWI_BUS_CONFIG_BURST)((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x00000108))), ((((((sc))->sc_mem_bt)->read_4((((sc)) ->sc_mem_bh), (((0x00000108))))) | ((1 << 2) | (1 << 3)))))); |
| 6764 | |
| 6765 | if (bus->rw_rev < 5) { |
| 6766 | 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 | CSR_SETBITS_4(sc, BWI_CONF_LO,((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x00000fa8))), ((((((sc))->sc_mem_bt)->read_4((((sc)) ->sc_mem_bh), (((0x00000fa8))))) | (((2) * ((((0x00000007) - 1) & (0x00000007)) ^ (0x00000007))) | ((3) * ((((0x00000070 ) - 1) & (0x00000070)) ^ (0x00000070)))))))) |
| 6776 | __SHIFTIN(BWI_CONF_LO_SERVTO,((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x00000fa8))), ((((((sc))->sc_mem_bt)->read_4((((sc)) ->sc_mem_bh), (((0x00000fa8))))) | (((2) * ((((0x00000007) - 1) & (0x00000007)) ^ (0x00000007))) | ((3) * ((((0x00000070 ) - 1) & (0x00000070)) ^ (0x00000070)))))))) |
| 6777 | BWI_CONF_LO_SERVTO_MASK) |((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x00000fa8))), ((((((sc))->sc_mem_bt)->read_4((((sc)) ->sc_mem_bh), (((0x00000fa8))))) | (((2) * ((((0x00000007) - 1) & (0x00000007)) ^ (0x00000007))) | ((3) * ((((0x00000070 ) - 1) & (0x00000070)) ^ (0x00000070)))))))) |
| 6778 | __SHIFTIN(BWI_CONF_LO_REQTO,((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x00000fa8))), ((((((sc))->sc_mem_bt)->read_4((((sc)) ->sc_mem_bh), (((0x00000fa8))))) | (((2) * ((((0x00000007) - 1) & (0x00000007)) ^ (0x00000007))) | ((3) * ((((0x00000070 ) - 1) & (0x00000070)) ^ (0x00000070)))))))) |
| 6779 | BWI_CONF_LO_REQTO_MASK))((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x00000fa8))), ((((((sc))->sc_mem_bt)->read_4((((sc)) ->sc_mem_bh), (((0x00000fa8))))) | (((2) * ((((0x00000007) - 1) & (0x00000007)) ^ (0x00000007))) | ((3) * ((((0x00000070 ) - 1) & (0x00000070)) ^ (0x00000070)))))))); |
| 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 | if (BWI_REGWIN_EXIST(com)((com)->rw_flags & 0x1)) { |
| 6786 | error = bwi_regwin_switch(sc, com, NULL((void *)0)); |
| 6787 | if (error) |
| 6788 | return (error); |
| 6789 | } |
| 6790 | |
| 6791 | /* Let bus know what we have changed */ |
| 6792 | CSR_WRITE_4(sc, BWI_BUS_ADDR, BWI_BUS_ADDR_MAGIC)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000050 )), ((0xfd8)))); |
| 6793 | CSR_READ_4(sc, BWI_BUS_ADDR)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000050 )))); /* Flush */ |
| 6794 | CSR_WRITE_4(sc, BWI_BUS_DATA, 0)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000054 )), ((0)))); |
| 6795 | CSR_READ_4(sc, BWI_BUS_DATA)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000054 )))); /* Flush */ |
| 6796 | |
| 6797 | if (BWI_REGWIN_EXIST(com)((com)->rw_flags & 0x1)) { |
| 6798 | error = bwi_regwin_switch(sc, bus, NULL((void *)0)); |
| 6799 | if (error) |
| 6800 | return (error); |
| 6801 | } |
| 6802 | } else if (bus->rw_rev >= 11) { |
| 6803 | /* |
| 6804 | * Enable memory read multiple |
| 6805 | */ |
| 6806 | CSR_SETBITS_4(sc, BWI_BUS_CONFIG, BWI_BUS_CONFIG_MRM)((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x00000108))), ((((((sc))->sc_mem_bt)->read_4((((sc)) ->sc_mem_bh), (((0x00000108))))) | ((1 << 5)))))); |
| 6807 | } |
| 6808 | } else { |
| 6809 | /* TODO: PCIE */ |
| 6810 | } |
| 6811 | |
| 6812 | sc->sc_flags |= BWI_F_BUS_INITED0x1; |
| 6813 | back: |
| 6814 | return (bwi_regwin_switch(sc, old, NULL((void *)0))); |
| 6815 | } |
| 6816 | |
| 6817 | void |
| 6818 | bwi_get_card_flags(struct bwi_softc *sc) |
| 6819 | { |
| 6820 | sc->sc_card_flags = bwi_read_sprom(sc, BWI_SPROM_CARD_FLAGS0x72); |
| 6821 | if (sc->sc_card_flags == 0xffff) |
| 6822 | sc->sc_card_flags = 0; |
| 6823 | |
| 6824 | if (sc->sc_pci_subvid == PCI_VENDOR_APPLE0x106b && |
| 6825 | sc->sc_pci_subdid == 0x4e && /* XXX */ |
| 6826 | sc->sc_pci_revid > 0x40) |
| 6827 | sc->sc_card_flags |= BWI_CARD_F_PA_GPIO9(1 << 1); |
| 6828 | |
| 6829 | DPRINTF(1, "%s: card flags 0x%04x\n", |
| 6830 | sc->sc_dev.dv_xname, sc->sc_card_flags); |
| 6831 | } |
| 6832 | |
| 6833 | void |
| 6834 | bwi_get_eaddr(struct bwi_softc *sc, uint16_t eaddr_ofs, uint8_t *eaddr) |
| 6835 | { |
| 6836 | int i; |
| 6837 | |
| 6838 | for (i = 0; i < 3; ++i) { |
| 6839 | *((uint16_t *)eaddr + i) = |
| 6840 | htobe16(bwi_read_sprom(sc, eaddr_ofs + 2 * i))(__uint16_t)(__builtin_constant_p(bwi_read_sprom(sc, eaddr_ofs + 2 * i)) ? (__uint16_t)(((__uint16_t)(bwi_read_sprom(sc, eaddr_ofs + 2 * i)) & 0xffU) << 8 | ((__uint16_t)(bwi_read_sprom (sc, eaddr_ofs + 2 * i)) & 0xff00U) >> 8) : __swap16md (bwi_read_sprom(sc, eaddr_ofs + 2 * i))); |
| 6841 | } |
| 6842 | } |
| 6843 | |
| 6844 | void |
| 6845 | 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 | bzero(freq, sizeof(*freq))__builtin_bzero((freq), (sizeof(*freq))); |
| 6853 | com = &sc->sc_com_regwin; |
| 6854 | |
| 6855 | KASSERT(BWI_REGWIN_EXIST(com))((((com)->rw_flags & 0x1)) ? (void)0 : __assert("diagnostic " , "/usr/src/sys/dev/ic/bwi.c", 6855, "BWI_REGWIN_EXIST(com)") ); |
| 6856 | KASSERT(sc->sc_cur_regwin == com)((sc->sc_cur_regwin == com) ? (void)0 : __assert("diagnostic " , "/usr/src/sys/dev/ic/bwi.c", 6856, "sc->sc_cur_regwin == com" )); |
| 6857 | KASSERT(sc->sc_cap & BWI_CAP_CLKMODE)((sc->sc_cap & (1 << 18)) ? (void)0 : __assert("diagnostic " , "/usr/src/sys/dev/ic/bwi.c", 6857, "sc->sc_cap & BWI_CAP_CLKMODE" )); |
| 6858 | |
| 6859 | /* |
| 6860 | * Calculate clock frequency |
| 6861 | */ |
| 6862 | src = -1; |
| 6863 | div = 0; |
| 6864 | if (com->rw_rev < 6) { |
| 6865 | val = (sc->sc_conf_read)(sc, BWI_PCIR_GPIO_OUT0x000000b4); |
| 6866 | if (val & BWI_PCIM_GPIO_OUT_CLKSRC(1 << 4)) { |
| 6867 | src = BWI_CLKSRC_PCI2; |
| 6868 | div = 64; |
| 6869 | } else { |
| 6870 | src = BWI_CLKSRC_CS_OSC1; |
| 6871 | div = 32; |
| 6872 | } |
| 6873 | } else if (com->rw_rev < 10) { |
| 6874 | val = CSR_READ_4(sc, BWI_CLOCK_CTRL)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x000000b8 )))); |
| 6875 | |
| 6876 | src = __SHIFTOUT(val, BWI_CLOCK_CTRL_CLKSRC)(((val) & ((7 << 0))) / (((((7 << 0)) - 1) & ((7 << 0))) ^ ((7 << 0)))); |
| 6877 | if (src == BWI_CLKSRC_LP_OSC0) |
| 6878 | div = 1; |
| 6879 | else { |
| 6880 | div = (__SHIFTOUT(val, BWI_CLOCK_CTRL_FDIV)(((val) & ((0xffff << 16))) / (((((0xffff << 16 )) - 1) & ((0xffff << 16))) ^ ((0xffff << 16) ))) + 1) << 2; |
| 6881 | |
| 6882 | /* Unknown source */ |
| 6883 | if (src >= BWI_CLKSRC_MAX3) |
| 6884 | src = BWI_CLKSRC_CS_OSC1; |
| 6885 | } |
| 6886 | } else { |
| 6887 | val = CSR_READ_4(sc, BWI_CLOCK_INFO)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x000000c0 )))); |
| 6888 | |
| 6889 | src = BWI_CLKSRC_CS_OSC1; |
| 6890 | div = (__SHIFTOUT(val, BWI_CLOCK_INFO_FDIV)(((val) & ((0xffff << 16))) / (((((0xffff << 16 )) - 1) & ((0xffff << 16))) ^ ((0xffff << 16) ))) + 1) << 2; |
| 6891 | } |
| 6892 | |
| 6893 | KASSERT(src >= 0 && src < BWI_CLKSRC_MAX)((src >= 0 && src < 3) ? (void)0 : __assert("diagnostic " , "/usr/src/sys/dev/ic/bwi.c", 6893, "src >= 0 && src < BWI_CLKSRC_MAX" )); |
| 6894 | KASSERT(div != 0)((div != 0) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c" , 6894, "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 | freq->clkfreq_min = bwi_clkfreq[src].freq_min / div; |
| 6902 | 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 | } |
| 6907 | |
| 6908 | int |
| 6909 | bwi_set_clock_mode(struct bwi_softc *sc, enum bwi_clock_mode clk_mode) |
| 6910 | { |
| 6911 | struct bwi_regwin *old, *com; |
| 6912 | uint32_t clk_ctrl, clk_src; |
| 6913 | int error, pwr_off = 0; |
| 6914 | |
| 6915 | com = &sc->sc_com_regwin; |
| 6916 | if (!BWI_REGWIN_EXIST(com)((com)->rw_flags & 0x1)) |
| 6917 | return (0); |
| 6918 | |
| 6919 | if (com->rw_rev >= 10 || com->rw_rev < 6) |
| 6920 | 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 | if ((sc->sc_cap & BWI_CAP_CLKMODE(1 << 18)) == 0) |
| 6927 | return (0); |
| 6928 | |
| 6929 | error = bwi_regwin_switch(sc, com, &old); |
| 6930 | if (error) |
| 6931 | return (error); |
| 6932 | |
| 6933 | if (clk_mode == BWI_CLOCK_MODE_FAST) |
| 6934 | bwi_power_on(sc, 0); /* Don't turn on PLL */ |
| 6935 | |
| 6936 | clk_ctrl = CSR_READ_4(sc, BWI_CLOCK_CTRL)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x000000b8 )))); |
| 6937 | clk_src = __SHIFTOUT(clk_ctrl, BWI_CLOCK_CTRL_CLKSRC)(((clk_ctrl) & ((7 << 0))) / (((((7 << 0)) - 1 ) & ((7 << 0))) ^ ((7 << 0)))); |
| 6938 | |
| 6939 | switch (clk_mode) { |
| 6940 | case BWI_CLOCK_MODE_FAST: |
| 6941 | clk_ctrl &= ~BWI_CLOCK_CTRL_SLOW(1 << 11); |
| 6942 | clk_ctrl |= BWI_CLOCK_CTRL_IGNPLL(1 << 12); |
| 6943 | break; |
| 6944 | case BWI_CLOCK_MODE_SLOW: |
| 6945 | clk_ctrl |= BWI_CLOCK_CTRL_SLOW(1 << 11); |
| 6946 | break; |
| 6947 | case BWI_CLOCK_MODE_DYN: |
| 6948 | clk_ctrl &= ~(BWI_CLOCK_CTRL_SLOW(1 << 11) | |
| 6949 | BWI_CLOCK_CTRL_IGNPLL(1 << 12) | |
| 6950 | BWI_CLOCK_CTRL_NODYN(1 << 13)); |
| 6951 | if (clk_src != BWI_CLKSRC_CS_OSC1) { |
| 6952 | clk_ctrl |= BWI_CLOCK_CTRL_NODYN(1 << 13); |
| 6953 | pwr_off = 1; |
| 6954 | } |
| 6955 | break; |
| 6956 | } |
| 6957 | CSR_WRITE_4(sc, BWI_CLOCK_CTRL, clk_ctrl)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x000000b8 )), ((clk_ctrl)))); |
| 6958 | |
| 6959 | if (pwr_off) |
| 6960 | bwi_power_off(sc, 0); /* Leave PLL as it is */ |
| 6961 | |
| 6962 | return (bwi_regwin_switch(sc, old, NULL((void *)0))); |
| 6963 | } |
| 6964 | |
| 6965 | int |
| 6966 | bwi_set_clock_delay(struct bwi_softc *sc) |
| 6967 | { |
| 6968 | struct bwi_regwin *old, *com; |
| 6969 | int error; |
| 6970 | |
| 6971 | com = &sc->sc_com_regwin; |
| 6972 | if (!BWI_REGWIN_EXIST(com)((com)->rw_flags & 0x1)) |
| 6973 | return (0); |
| 6974 | |
| 6975 | error = bwi_regwin_switch(sc, com, &old); |
| 6976 | if (error) |
| 6977 | return (error); |
| 6978 | |
| 6979 | if (sc->sc_bbp_id == BWI_BBPID_BCM43210x4321) { |
| 6980 | if (sc->sc_bbp_rev == 0) |
| 6981 | CSR_WRITE_4(sc, BWI_CONTROL, BWI_CONTROL_MAGIC0)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000028 )), ((0x3a4)))); |
| 6982 | else if (sc->sc_bbp_rev == 1) |
| 6983 | CSR_WRITE_4(sc, BWI_CONTROL, BWI_CONTROL_MAGIC1)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000028 )), ((0xa4)))); |
| 6984 | } |
| 6985 | |
| 6986 | if (sc->sc_cap & BWI_CAP_CLKMODE(1 << 18)) { |
| 6987 | if (com->rw_rev >= 10) |
| 6988 | CSR_FILT_SETBITS_4(sc, BWI_CLOCK_INFO, 0xffff, 0x40000)((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x000000c0))), (((((((sc))->sc_mem_bt)->read_4((((sc) )->sc_mem_bh), (((0x000000c0))))) & (0xffff)) | (0x40000 ))))); |
| 6989 | else { |
| 6990 | struct bwi_clock_freq freq; |
| 6991 | |
| 6992 | bwi_get_clock_freq(sc, &freq); |
| 6993 | CSR_WRITE_4(sc, BWI_PLL_ON_DELAY,(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0xb0 )), (((((freq.clkfreq_max * 150) + ((1000000) - 1)) / (1000000 )))))) |
| 6994 | howmany(freq.clkfreq_max * 150, 1000000))(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0xb0 )), (((((freq.clkfreq_max * 150) + ((1000000) - 1)) / (1000000 )))))); |
| 6995 | CSR_WRITE_4(sc, BWI_FREQ_SEL_DELAY,(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0xb4 )), (((((freq.clkfreq_max * 15) + ((1000000) - 1)) / (1000000 )))))) |
| 6996 | howmany(freq.clkfreq_max * 15, 1000000))(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0xb4 )), (((((freq.clkfreq_max * 15) + ((1000000) - 1)) / (1000000 )))))); |
| 6997 | } |
| 6998 | } |
| 6999 | |
| 7000 | return (bwi_regwin_switch(sc, old, NULL((void *)0))); |
| 7001 | } |
| 7002 | |
| 7003 | int |
| 7004 | bwi_init(struct ifnet *ifp) |
| 7005 | { |
| 7006 | struct bwi_softc *sc = ifp->if_softc; |
| 7007 | |
| 7008 | bwi_init_statechg(sc, 1); |
| 7009 | |
| 7010 | return (0); |
| 7011 | } |
| 7012 | |
| 7013 | void |
| 7014 | bwi_init_statechg(struct bwi_softc *sc, int statechg) |
| 7015 | { |
| 7016 | struct ieee80211com *ic = &sc->sc_ic; |
| 7017 | struct ifnet *ifp = &ic->ic_ific_ac.ac_if; |
| 7018 | struct bwi_mac *mac; |
| 7019 | int error; |
| 7020 | |
| 7021 | DPRINTF(1, "%s: %s\n", sc->sc_dev.dv_xname, __func__); |
| 7022 | |
| 7023 | error = bwi_stop(sc, statechg); |
| 7024 | if (error) { |
| 7025 | DPRINTF(1, "%s: can't stop\n", sc->sc_dev.dv_xname); |
| 7026 | return; |
| 7027 | } |
| 7028 | |
| 7029 | /* power on cardbus socket */ |
| 7030 | if (sc->sc_enable != NULL((void *)0)) |
| 7031 | (*sc->sc_enable)(sc); |
| 7032 | |
| 7033 | bwi_bbp_power_on(sc, BWI_CLOCK_MODE_FAST); |
| 7034 | |
| 7035 | /* TODO: 2 MAC */ |
| 7036 | |
| 7037 | mac = &sc->sc_mac[0]; |
| 7038 | error = bwi_regwin_switch(sc, &mac->mac_regwin, NULL((void *)0)); |
| 7039 | if (error) |
| 7040 | goto back; |
| 7041 | |
| 7042 | error = bwi_mac_init(mac); |
| 7043 | if (error) |
| 7044 | goto back; |
| 7045 | |
| 7046 | bwi_bbp_power_on(sc, BWI_CLOCK_MODE_DYN); |
| 7047 | |
| 7048 | IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl))__builtin_memcpy((ic->ic_myaddr), (((caddr_t)((ifp->if_sadl )->sdl_data + (ifp->if_sadl)->sdl_nlen))), (6)); |
| 7049 | |
| 7050 | bwi_set_bssid(sc, bwi_zero_addr); /* Clear BSSID */ |
| 7051 | bwi_set_addr_filter(sc, BWI_ADDR_FILTER_MYADDR0, ic->ic_myaddr); |
| 7052 | |
| 7053 | bwi_mac_reset_hwkeys(mac); |
| 7054 | |
| 7055 | if ((mac->mac_flags & BWI_MAC_F_HAS_TXSTATS0x4) == 0) { |
| 7056 | int i; |
| 7057 | |
| 7058 | #define NRETRY 1000 |
| 7059 | /* |
| 7060 | * Drain any possible pending TX status |
| 7061 | */ |
| 7062 | for (i = 0; i < NRETRY; ++i) { |
| 7063 | if ((CSR_READ_4(sc, BWI_TXSTATUS_0)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000170 )))) & |
| 7064 | BWI_TXSTATUS_0_MORE(1 << 0)) == 0) |
| 7065 | break; |
| 7066 | CSR_READ_4(sc, BWI_TXSTATUS_1)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000174 )))); |
| 7067 | } |
| 7068 | if (i == NRETRY) |
| 7069 | printf("%s: can't drain TX status\n", |
| 7070 | sc->sc_dev.dv_xname); |
| 7071 | #undef NRETRY |
| 7072 | } |
| 7073 | |
| 7074 | if (mac->mac_phy.phy_mode == IEEE80211_MODE_11G) |
| 7075 | bwi_mac_updateslot(mac, 1); |
| 7076 | |
| 7077 | /* Start MAC */ |
| 7078 | error = bwi_mac_start(mac); |
| 7079 | if (error) |
| 7080 | goto back; |
| 7081 | |
| 7082 | /* Enable intrs */ |
| 7083 | bwi_enable_intrs(sc, BWI_INIT_INTRS((1 << 0) | (1 << 1) | (1 << 2) | (1 << 5) | (1 << 6) | (1 << 9) | (1 << 11) | (1 << 15) | (1 << 16) | (1 << 18) | (1 << 28) | ( 1 << 29))); |
| 7084 | |
| 7085 | ifp->if_flags |= IFF_RUNNING0x40; |
| 7086 | ifq_clr_oactive(&ifp->if_snd); |
| 7087 | |
| 7088 | if (statechg) { |
| 7089 | if (ic->ic_opmode != IEEE80211_M_MONITOR) { |
| 7090 | ieee80211_new_state(ic, IEEE80211_S_SCAN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_SCAN), (-1))); |
| 7091 | } else { |
| 7092 | ieee80211_new_state(ic, IEEE80211_S_RUN, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_RUN), (-1))); |
| 7093 | } |
| 7094 | } else { |
| 7095 | ieee80211_new_state(ic, ic->ic_state, -1)(((ic)->ic_newstate)((ic), (ic->ic_state), (-1))); |
| 7096 | } |
| 7097 | |
| 7098 | back: |
| 7099 | if (error) |
| 7100 | bwi_stop(sc, 1); |
| 7101 | else |
| 7102 | bwi_start(ifp); |
| 7103 | } |
| 7104 | |
| 7105 | int |
| 7106 | bwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) |
| 7107 | { |
| 7108 | struct bwi_softc *sc = ifp->if_softc; |
| 7109 | struct ieee80211com *ic = &sc->sc_ic; |
| 7110 | int s, error = 0; |
| 7111 | uint8_t chan; |
| 7112 | |
| 7113 | s = splnet()splraise(0x4); |
| 7114 | |
| 7115 | switch (cmd) { |
| 7116 | case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((12))): |
| 7117 | ifp->if_flags |= IFF_UP0x1; |
| 7118 | /* FALLTHROUGH */ |
| 7119 | case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((16))): |
| 7120 | if (ifp->if_flags & IFF_UP0x1) { |
| 7121 | if ((ifp->if_flags & IFF_RUNNING0x40) == 0) |
| 7122 | bwi_init(ifp); |
| 7123 | } else { |
| 7124 | if (ifp->if_flags & IFF_RUNNING0x40) |
| 7125 | bwi_stop(sc, 1); |
| 7126 | } |
| 7127 | break; |
| 7128 | case SIOCS80211CHANNEL((unsigned long)0x80000000 | ((sizeof(struct ieee80211chanreq ) & 0x1fff) << 16) | ((('i')) << 8) | ((238)) ): |
| 7129 | /* allow fast channel switching in monitor mode */ |
| 7130 | error = ieee80211_ioctl(ifp, cmd, data); |
| 7131 | if (error == ENETRESET52 && |
| 7132 | ic->ic_opmode == IEEE80211_M_MONITOR) { |
| 7133 | if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) == |
| 7134 | (IFF_UP0x1 | IFF_RUNNING0x40)) { |
| 7135 | ic->ic_bss->ni_chan = ic->ic_ibss_chan; |
| 7136 | chan = ieee80211_chan2ieee(ic, |
| 7137 | ic->ic_bss->ni_chan); |
| 7138 | bwi_set_chan(sc, chan); |
| 7139 | } |
| 7140 | error = 0; |
| 7141 | } |
| 7142 | break; |
| 7143 | default: |
| 7144 | error = ieee80211_ioctl(ifp, cmd, data); |
| 7145 | break; |
| 7146 | } |
| 7147 | |
| 7148 | if (error == ENETRESET52) { |
| 7149 | if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) == |
| 7150 | (IFF_UP0x1 | IFF_RUNNING0x40)) |
| 7151 | bwi_init(ifp); |
| 7152 | error = 0; |
| 7153 | } |
| 7154 | |
| 7155 | splx(s)spllower(s); |
| 7156 | |
| 7157 | return (error); |
| 7158 | } |
| 7159 | |
| 7160 | void |
| 7161 | bwi_start(struct ifnet *ifp) |
| 7162 | { |
| 7163 | struct bwi_softc *sc = ifp->if_softc; |
| 7164 | struct ieee80211com *ic = &sc->sc_ic; |
| 7165 | struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING1]; |
| 7166 | int trans, idx; |
| 7167 | |
| 7168 | if (ifq_is_oactive(&ifp->if_snd) || (ifp->if_flags & IFF_RUNNING0x40) == 0) |
| 7169 | return; |
| 7170 | |
| 7171 | trans = 0; |
| 7172 | idx = tbd->tbd_idx; |
| 7173 | |
| 7174 | while (tbd->tbd_buf[idx].tb_mbuf == NULL((void *)0)) { |
| 7175 | struct ieee80211_frame *wh; |
| 7176 | struct ieee80211_node *ni; |
| 7177 | struct ieee80211_key *k; |
| 7178 | struct mbuf *m; |
| 7179 | int mgt_pkt = 0; |
| 7180 | |
| 7181 | m = mq_dequeue(&ic->ic_mgtq); |
| 7182 | if (m != NULL((void *)0)) { |
| 7183 | ni = m->m_pkthdrM_dat.MH.MH_pkthdr.ph_cookie; |
| 7184 | |
| 7185 | mgt_pkt = 1; |
| 7186 | } else { |
| 7187 | struct ether_header *eh; |
| 7188 | |
| 7189 | if (ic->ic_state != IEEE80211_S_RUN) |
| 7190 | break; |
| 7191 | |
| 7192 | m = ifq_dequeue(&ifp->if_snd); |
| 7193 | if (m == NULL((void *)0)) |
| 7194 | break; |
| 7195 | |
| 7196 | if (m->m_lenm_hdr.mh_len < sizeof(*eh)) { |
| 7197 | m = m_pullup(m, sizeof(*eh)); |
| 7198 | if (m == NULL((void *)0)) { |
| 7199 | ifp->if_oerrorsif_data.ifi_oerrors++; |
| 7200 | continue; |
| 7201 | } |
| 7202 | } |
| 7203 | eh = mtod(m, struct ether_header *)((struct ether_header *)((m)->m_hdr.mh_data)); |
| 7204 | |
| 7205 | ni = ieee80211_find_txnode(ic, eh->ether_dhost); |
| 7206 | if (ni == NULL((void *)0)) { |
| 7207 | m_freem(m); |
| 7208 | ifp->if_oerrorsif_data.ifi_oerrors++; |
| 7209 | continue; |
| 7210 | } |
| 7211 | |
| 7212 | /* TODO: PS */ |
| 7213 | #if NBPFILTER1 > 0 |
| 7214 | if (ifp->if_bpf != NULL((void *)0)) |
| 7215 | bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT(1 << 1)); |
| 7216 | #endif |
| 7217 | m = ieee80211_encap(ifp, m, &ni); |
| 7218 | if (m == NULL((void *)0)) |
| 7219 | continue; |
| 7220 | } |
| 7221 | #if NBPFILTER1 > 0 |
| 7222 | if (ic->ic_rawbpf != NULL((void *)0)) |
| 7223 | bpf_mtap(ic->ic_rawbpf, m, BPF_DIRECTION_OUT(1 << 1)); |
| 7224 | #endif |
| 7225 | wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data)); |
| 7226 | if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED0x40) { |
| 7227 | k = ieee80211_get_txkey(ic, wh, ni); |
| 7228 | if ((m = ieee80211_encrypt(ic, m, k)) == NULL((void *)0)) |
| 7229 | return; |
| 7230 | } |
| 7231 | wh = NULL((void *)0); /* Catch any invalid use */ |
| 7232 | |
| 7233 | if (mgt_pkt) { |
| 7234 | ieee80211_release_node(ic, ni); |
| 7235 | ni = NULL((void *)0); |
| 7236 | } |
| 7237 | |
| 7238 | if (bwi_encap(sc, idx, m, ni) != 0) { |
| 7239 | /* 'm' is freed in bwi_encap() if we reach here */ |
| 7240 | if (ni != NULL((void *)0)) |
| 7241 | ieee80211_release_node(ic, ni); |
| 7242 | ifp->if_oerrorsif_data.ifi_oerrors++; |
| 7243 | continue; |
| 7244 | } |
| 7245 | |
| 7246 | trans = 1; |
| 7247 | tbd->tbd_used++; |
| 7248 | idx = (idx + 1) % BWI_TX_NDESC128; |
| 7249 | |
| 7250 | if (tbd->tbd_used + BWI_TX_NSPRDESC2 >= BWI_TX_NDESC128) { |
| 7251 | ifq_set_oactive(&ifp->if_snd); |
| 7252 | break; |
| 7253 | } |
| 7254 | } |
| 7255 | tbd->tbd_idx = idx; |
| 7256 | |
| 7257 | if (trans) |
| 7258 | sc->sc_tx_timer = 5; |
| 7259 | ifp->if_timer = 1; |
| 7260 | } |
| 7261 | |
| 7262 | void |
| 7263 | bwi_watchdog(struct ifnet *ifp) |
| 7264 | { |
| 7265 | struct bwi_softc *sc = ifp->if_softc; |
| 7266 | |
| 7267 | ifp->if_timer = 0; |
| 7268 | |
| 7269 | if ((ifp->if_flags & IFF_RUNNING0x40) == 0) |
| 7270 | return; |
| 7271 | |
| 7272 | if (sc->sc_tx_timer) { |
| 7273 | if (--sc->sc_tx_timer == 0) { |
| 7274 | printf("%s: watchdog timeout\n", |
| 7275 | sc->sc_dev.dv_xname); |
| 7276 | ifp->if_oerrorsif_data.ifi_oerrors++; |
| 7277 | /* TODO */ |
| 7278 | } else |
| 7279 | ifp->if_timer = 1; |
| 7280 | } |
| 7281 | |
| 7282 | ieee80211_watchdog(ifp); |
| 7283 | } |
| 7284 | |
| 7285 | void |
| 7286 | bwi_newstate_begin(struct bwi_softc *sc, enum ieee80211_state nstate) |
| 7287 | { |
| 7288 | timeout_del(&sc->sc_scan_ch); |
| 7289 | timeout_del(&sc->sc_calib_ch); |
| 7290 | |
| 7291 | bwi_led_newstate(sc, nstate); |
| 7292 | |
| 7293 | if (nstate == IEEE80211_S_INIT) |
| 7294 | sc->sc_txpwrcb_type = BWI_TXPWR_INIT; |
| 7295 | } |
| 7296 | |
| 7297 | int |
| 7298 | bwi_stop(struct bwi_softc *sc, int state_chg) |
| 7299 | { |
| 7300 | struct ieee80211com *ic = &sc->sc_ic; |
| 7301 | struct ifnet *ifp = &ic->ic_ific_ac.ac_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 | if (state_chg) |
| 7308 | ieee80211_new_state(ic, IEEE80211_S_INIT, -1)(((ic)->ic_newstate)((ic), (IEEE80211_S_INIT), (-1))); |
| 7309 | else |
| 7310 | bwi_newstate_begin(sc, IEEE80211_S_INIT); |
| 7311 | |
| 7312 | if (ifp->if_flags & IFF_RUNNING0x40) { |
| 7313 | KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC)((sc->sc_cur_regwin->rw_type == 0x812) ? (void)0 : __assert ("diagnostic ", "/usr/src/sys/dev/ic/bwi.c", 7313, "sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC" )); |
| 7314 | mac = (struct bwi_mac *)sc->sc_cur_regwin; |
| 7315 | |
| 7316 | bwi_disable_intrs(sc, BWI_ALL_INTRS0xffffffff); |
| 7317 | CSR_READ_4(sc, BWI_MAC_INTR_MASK)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x0000012c )))); |
| 7318 | bwi_mac_stop(mac); |
| 7319 | } |
| 7320 | |
| 7321 | for (i = 0; i < sc->sc_nmac; ++i) { |
| 7322 | struct bwi_regwin *old_rw; |
| 7323 | |
| 7324 | mac = &sc->sc_mac[i]; |
| 7325 | if ((mac->mac_flags & BWI_MAC_F_INITED0x8) == 0) |
| 7326 | continue; |
| 7327 | |
| 7328 | error = bwi_regwin_switch(sc, &mac->mac_regwin, &old_rw); |
| 7329 | if (error) |
| 7330 | continue; |
| 7331 | |
| 7332 | bwi_mac_shutdown(mac); |
| 7333 | pwr_off = 1; |
| 7334 | |
| 7335 | bwi_regwin_switch(sc, old_rw, NULL((void *)0)); |
| 7336 | } |
| 7337 | |
| 7338 | if (pwr_off) |
| 7339 | bwi_bbp_power_off(sc); |
| 7340 | |
| 7341 | sc->sc_tx_timer = 0; |
| 7342 | ifp->if_timer = 0; |
| 7343 | ifp->if_flags &= ~IFF_RUNNING0x40; |
| 7344 | ifq_clr_oactive(&ifp->if_snd); |
| 7345 | |
| 7346 | /* power off cardbus socket */ |
| 7347 | if (sc->sc_disable) |
| 7348 | sc->sc_disable(sc); |
| 7349 | |
| 7350 | return (0); |
| 7351 | } |
| 7352 | |
| 7353 | int |
| 7354 | bwi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) |
| 7355 | { |
| 7356 | struct bwi_softc *sc = ic->ic_ific_ac.ac_if.if_softc; |
| 7357 | struct ieee80211_node *ni; |
| 7358 | int error; |
| 7359 | uint8_t chan; |
| 7360 | |
| 7361 | timeout_del(&sc->sc_amrr_ch); |
| 7362 | |
| 7363 | bwi_newstate_begin(sc, nstate); |
| 7364 | |
| 7365 | if (nstate == IEEE80211_S_INIT) |
| 7366 | goto back; |
| 7367 | |
| 7368 | chan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan); |
| 7369 | error = bwi_set_chan(sc, chan); |
| 7370 | if (error) { |
| 7371 | printf("%s: can't set channel to %u\n", |
| 7372 | sc->sc_dev.dv_xname, |
| 7373 | ieee80211_chan2ieee(ic, ic->ic_des_chan)); |
| 7374 | return (error); |
| 7375 | } |
| 7376 | |
| 7377 | if (ic->ic_opmode == IEEE80211_M_MONITOR) { |
| 7378 | /* Nothing to do */ |
| 7379 | } else if (nstate == IEEE80211_S_RUN) { |
| 7380 | struct bwi_mac *mac; |
| 7381 | |
| 7382 | ni = ic->ic_bss; |
| 7383 | |
| 7384 | bwi_set_bssid(sc, ic->ic_bss->ni_bssid); |
| 7385 | |
| 7386 | KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC)((sc->sc_cur_regwin->rw_type == 0x812) ? (void)0 : __assert ("diagnostic ", "/usr/src/sys/dev/ic/bwi.c", 7386, "sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC" )); |
| 7387 | mac = (struct bwi_mac *)sc->sc_cur_regwin; |
| 7388 | |
| 7389 | /* Initial TX power calibration */ |
| 7390 | bwi_mac_calibrate_txpower(mac, BWI_TXPWR_INIT); |
| 7391 | #ifdef notyet |
| 7392 | sc->sc_txpwrcb_type = BWI_TXPWR_FORCE; |
| 7393 | #else |
| 7394 | sc->sc_txpwrcb_type = BWI_TXPWR_CALIB; |
| 7395 | #endif |
| 7396 | if (ic->ic_opmode == IEEE80211_M_STA) { |
| 7397 | /* fake a join to init the tx rate */ |
| 7398 | bwi_newassoc(ic, ni, 1); |
| 7399 | } |
| 7400 | |
| 7401 | if (ic->ic_opmode != IEEE80211_M_MONITOR) { |
| 7402 | /* start automatic rate control timer */ |
| 7403 | if (ic->ic_fixed_rate == -1) |
| 7404 | timeout_add_msec(&sc->sc_amrr_ch, 500); |
| 7405 | } |
| 7406 | } else |
| 7407 | bwi_set_bssid(sc, bwi_zero_addr); |
| 7408 | |
| 7409 | back: |
| 7410 | error = sc->sc_newstate(ic, nstate, arg); |
| 7411 | |
| 7412 | if (nstate == IEEE80211_S_SCAN) { |
| 7413 | timeout_add_msec(&sc->sc_scan_ch, sc->sc_dwell_time); |
| 7414 | } else if (nstate == IEEE80211_S_RUN) { |
| 7415 | /* XXX 15 seconds */ |
| 7416 | timeout_add_sec(&sc->sc_calib_ch, 1); |
| 7417 | } |
| 7418 | |
| 7419 | return (error); |
| 7420 | } |
| 7421 | |
| 7422 | int |
| 7423 | bwi_media_change(struct ifnet *ifp) |
| 7424 | { |
| 7425 | int error; |
| 7426 | |
| 7427 | error = ieee80211_media_change(ifp); |
| 7428 | if (error != ENETRESET52) |
| 7429 | return (error); |
| 7430 | |
| 7431 | if ((ifp->if_flags & (IFF_UP0x1 | IFF_RUNNING0x40)) == (IFF_UP0x1 | IFF_RUNNING0x40)) |
| 7432 | bwi_init(ifp); |
| 7433 | |
| 7434 | return (0); |
| 7435 | } |
| 7436 | |
| 7437 | void |
| 7438 | bwi_iter_func(void *arg, struct ieee80211_node *ni) |
| 7439 | { |
| 7440 | struct bwi_softc *sc = arg; |
| 7441 | struct bwi_node *bn = (struct bwi_node *)ni; |
| 7442 | |
| 7443 | ieee80211_amrr_choose(&sc->sc_amrr, ni, &bn->amn); |
| 7444 | } |
| 7445 | |
| 7446 | void |
| 7447 | bwi_amrr_timeout(void *arg) |
| 7448 | { |
| 7449 | struct bwi_softc *sc = arg; |
| 7450 | struct ieee80211com *ic = &sc->sc_ic; |
| 7451 | |
| 7452 | if (ic->ic_opmode == IEEE80211_M_STA) |
| 7453 | bwi_iter_func(sc, ic->ic_bss); |
| 7454 | #ifndef IEEE80211_STA_ONLY |
| 7455 | else |
| 7456 | ieee80211_iterate_nodes(ic, bwi_iter_func, sc); |
| 7457 | #endif |
| 7458 | |
| 7459 | timeout_add_msec(&sc->sc_amrr_ch, 500); |
| 7460 | } |
| 7461 | |
| 7462 | void |
| 7463 | bwi_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew) |
| 7464 | { |
| 7465 | struct bwi_softc *sc = ic->ic_ific_ac.ac_if.if_softc; |
| 7466 | int i; |
| 7467 | |
| 7468 | DPRINTF(1, "%s: %s\n", sc->sc_dev.dv_xname, __func__); |
| 7469 | |
| 7470 | ieee80211_amrr_node_init(&sc->sc_amrr, &((struct bwi_node *)ni)->amn); |
| 7471 | |
| 7472 | /* set rate to some reasonable initial value */ |
| 7473 | for (i = ni->ni_rates.rs_nrates - 1; |
| 7474 | i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL0x7f) > 72; |
| 7475 | i--); |
| 7476 | |
| 7477 | ni->ni_txrate = i; |
| 7478 | } |
| 7479 | |
| 7480 | struct ieee80211_node * |
| 7481 | bwi_node_alloc(struct ieee80211com *ic) |
| 7482 | { |
| 7483 | struct bwi_node *bn; |
| 7484 | |
| 7485 | bn = malloc(sizeof(*bn), M_DEVBUF2, M_NOWAIT0x0002 | M_ZERO0x0008); |
| 7486 | if (bn == NULL((void *)0)) |
| 7487 | return (NULL((void *)0)); |
| 7488 | |
| 7489 | return ((struct ieee80211_node *)bn); |
| 7490 | } |
| 7491 | |
| 7492 | struct uvm_constraint_range bwi_constraint = { 0x0, (0x40000000 - 1) }; |
| 7493 | struct kmem_pa_mode bwi_pa_mode = { |
| 7494 | .kp_align = BWI_RING_ALIGN0x1000, |
| 7495 | .kp_constraint = &bwi_constraint, |
| 7496 | .kp_zero = 1 |
| 7497 | }; |
| 7498 | |
| 7499 | int |
| 7500 | 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 | for (i = 0; i < sc->sc_nmac; ++i) { |
| 7509 | if (sc->sc_mac[i].mac_flags & BWI_MAC_F_HAS_TXSTATS0x4) { |
| 7510 | has_txstats = 1; |
| 7511 | break; |
| 7512 | } |
| 7513 | } |
| 7514 | |
| 7515 | 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 | sc->sc_newbuf = bwi_newbuf30; |
| 7522 | |
| 7523 | /* XXX implement txstats for 30bit? */ |
| 7524 | 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 | sc->sc_init_tx_ring = bwi_init_tx_ring32; |
| 7532 | sc->sc_free_tx_ring = bwi_free_tx_ring32; |
| 7533 | sc->sc_init_rx_ring = bwi_init_rx_ring32; |
| 7534 | sc->sc_free_rx_ring = bwi_free_rx_ring32; |
| 7535 | if (sc->sc_newbuf == NULL((void *)0)) |
| 7536 | sc->sc_newbuf = bwi_newbuf; |
| 7537 | sc->sc_setup_rxdesc = bwi_setup_rx_desc32; |
| 7538 | sc->sc_setup_txdesc = bwi_setup_tx_desc32; |
| 7539 | sc->sc_rxeof = bwi_rxeof32; |
| 7540 | sc->sc_start_tx = bwi_start_tx32; |
| 7541 | if (has_txstats) { |
| 7542 | sc->sc_init_txstats = bwi_init_txstats32; |
| 7543 | sc->sc_free_txstats = bwi_free_txstats32; |
| 7544 | sc->sc_txeof_status = bwi_txeof_status32; |
| 7545 | } |
| 7546 | break; |
| 7547 | |
| 7548 | default: |
| 7549 | panic("unsupported bus space type %d", sc->sc_bus_space); |
| 7550 | } |
| 7551 | |
| 7552 | KASSERT(desc_sz != 0)((desc_sz != 0) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c" , 7552, "desc_sz != 0")); |
| 7553 | KASSERT(txrx_ctrl_step != 0)((txrx_ctrl_step != 0) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c" , 7553, "txrx_ctrl_step != 0")); |
| 7554 | |
| 7555 | tx_ring_sz = roundup(desc_sz * BWI_TX_NDESC, BWI_RING_ALIGN)((((desc_sz * 128)+((0x1000)-1))/(0x1000))*(0x1000)); |
| 7556 | rx_ring_sz = roundup(desc_sz * BWI_RX_NDESC, BWI_RING_ALIGN)((((desc_sz * 64)+((0x1000)-1))/(0x1000))*(0x1000)); |
| 7557 | |
| 7558 | s = splvm()splraise(0xa); |
| 7559 | |
| 7560 | #define TXRX_CTRL(idx) (BWI_TXRX_CTRL_BASE0x200 + (idx) * txrx_ctrl_step) |
| 7561 | /* |
| 7562 | * Create TX ring DMA stuffs |
| 7563 | */ |
| 7564 | for (i = 0; i < BWI_TX_NRING6; ++i) { |
| 7565 | error = bwi_dma_ring_alloc(sc, |
| 7566 | &sc->sc_tx_rdata[i], tx_ring_sz, TXRX_CTRL(i)); |
| 7567 | if (error) { |
| 7568 | printf("%s: %dth TX ring DMA alloc failed\n", |
| 7569 | sc->sc_dev.dv_xname, i); |
| 7570 | bwi_dma_free(sc); |
| 7571 | splx(s)spllower(s); |
| 7572 | return (error); |
| 7573 | } |
| 7574 | } |
| 7575 | |
| 7576 | /* |
| 7577 | * Create RX ring DMA stuffs |
| 7578 | */ |
| 7579 | error = bwi_dma_ring_alloc(sc, &sc->sc_rx_rdata, |
| 7580 | rx_ring_sz, TXRX_CTRL(0)); |
| 7581 | if (error) { |
| 7582 | printf("%s: RX ring DMA alloc failed\n", sc->sc_dev.dv_xname); |
| 7583 | bwi_dma_free(sc); |
| 7584 | splx(s)spllower(s); |
| 7585 | return (error); |
| 7586 | } |
| 7587 | |
| 7588 | if (has_txstats) { |
| 7589 | error = bwi_dma_txstats_alloc(sc, TXRX_CTRL(3), desc_sz); |
| 7590 | if (error) { |
| 7591 | printf("%s: TX stats DMA alloc failed\n", |
| 7592 | sc->sc_dev.dv_xname); |
| 7593 | bwi_dma_free(sc); |
| 7594 | splx(s)spllower(s); |
| 7595 | return (error); |
| 7596 | } |
| 7597 | } |
| 7598 | #undef TXRX_CTRL |
| 7599 | |
| 7600 | if (sc->sc_bus_space == BWI_BUS_SPACE_30BIT) |
| 7601 | error = bwi_dma_mbuf_create30(sc); |
| 7602 | else |
| 7603 | error = bwi_dma_mbuf_create(sc); |
| 7604 | if (error) |
| 7605 | bwi_dma_free(sc); |
| 7606 | |
| 7607 | splx(s)spllower(s); |
| 7608 | |
| 7609 | return (error); |
| 7610 | } |
| 7611 | |
| 7612 | void |
| 7613 | bwi_dma_free(struct bwi_softc *sc) |
| 7614 | { |
| 7615 | struct bwi_ring_data *rd; |
| 7616 | int i; |
| 7617 | |
| 7618 | for (i = 0; i < BWI_TX_NRING6; ++i) { |
| 7619 | rd = &sc->sc_tx_rdata[i]; |
| 7620 | |
| 7621 | if (rd->rdata_desc != NULL((void *)0)) { |
| 7622 | bus_dmamap_unload(sc->sc_dmat, rd->rdata_dmap)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (rd-> rdata_dmap)); |
| 7623 | km_free(rd->rdata_desc, rd->rdata_ring_sz, |
| 7624 | &kv_intrsafe, &bwi_pa_mode); |
| 7625 | rd->rdata_desc = NULL((void *)0); |
| 7626 | } |
| 7627 | } |
| 7628 | |
| 7629 | rd = &sc->sc_rx_rdata; |
| 7630 | |
| 7631 | if (rd->rdata_desc != NULL((void *)0)) { |
| 7632 | bus_dmamap_unload(sc->sc_dmat, rd->rdata_dmap)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (rd-> rdata_dmap)); |
| 7633 | km_free(rd->rdata_desc, rd->rdata_ring_sz, |
| 7634 | &kv_intrsafe, &bwi_pa_mode); |
| 7635 | rd->rdata_desc = NULL((void *)0); |
| 7636 | } |
| 7637 | |
| 7638 | bwi_dma_txstats_free(sc); |
| 7639 | |
| 7640 | if (sc->sc_bus_space == BWI_BUS_SPACE_30BIT) { |
| 7641 | for (i = 0; i < BWI_TX_NRING6; ++i) { |
| 7642 | if (sc->sc_bounce_tx_data[i] != NULL((void *)0)) { |
| 7643 | km_free(sc->sc_bounce_tx_data[i], |
| 7644 | BWI_TX_NDESC128 * MCLBYTES(1 << 11), |
| 7645 | &kv_intrsafe, &bwi_pa_mode); |
| 7646 | sc->sc_bounce_tx_data[i] = NULL((void *)0); |
| 7647 | } |
| 7648 | } |
| 7649 | |
| 7650 | if (sc->sc_bounce_rx_data != NULL((void *)0)) { |
| 7651 | km_free(sc->sc_bounce_rx_data, BWI_RX_NDESC64 * MCLBYTES(1 << 11), |
| 7652 | &kv_intrsafe, &bwi_pa_mode); |
| 7653 | sc->sc_bounce_rx_data = NULL((void *)0); |
| 7654 | } |
| 7655 | } |
| 7656 | } |
| 7657 | |
| 7658 | int |
| 7659 | 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 | rd->rdata_desc = (caddr_t)km_alloc(size, &kv_intrsafe, &bwi_pa_mode, |
| 7666 | &kd_nowait); |
| 7667 | if (rd->rdata_desc == NULL((void *)0)) { |
| 7668 | printf(": could not allocate ring DMA memory\n"); |
| 7669 | return (ENOMEM12); |
| 7670 | } |
| 7671 | |
| 7672 | error = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (size ), (1), (size), (0), (0x0001), (&rd->rdata_dmap)) |
| 7673 | BUS_DMA_NOWAIT, &rd->rdata_dmap)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (size ), (1), (size), (0), (0x0001), (&rd->rdata_dmap)); |
| 7674 | if (error) { |
| 7675 | printf(": cannot create ring DMA map (error %d)\n", error); |
| 7676 | km_free(rd->rdata_desc, size, &kv_intrsafe, &bwi_pa_mode); |
| 7677 | rd->rdata_desc = NULL((void *)0); |
| 7678 | return (error); |
| 7679 | } |
| 7680 | |
| 7681 | error = bus_dmamap_load(sc->sc_dmat, rd->rdata_dmap, rd->rdata_desc,(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (rd-> rdata_dmap), (rd->rdata_desc), (size), (((void *)0)), (0x0000 )) |
| 7682 | size, NULL, BUS_DMA_WAITOK)(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (rd-> rdata_dmap), (rd->rdata_desc), (size), (((void *)0)), (0x0000 )); |
| 7683 | if (error) { |
| 7684 | printf("%s: can't load DMA mem\n", sc->sc_dev.dv_xname); |
| 7685 | bus_dmamap_destroy(sc->sc_dmat, rd->rdata_dmap)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (rd ->rdata_dmap)); |
| 7686 | km_free(rd->rdata_desc, size, &kv_intrsafe, &bwi_pa_mode); |
| 7687 | rd->rdata_desc = NULL((void *)0); |
| 7688 | return (error); |
| 7689 | } |
| 7690 | |
| 7691 | rd->rdata_ring_sz = size; |
| 7692 | rd->rdata_paddr = rd->rdata_dmap->dm_segs[0].ds_addr; |
| 7693 | rd->rdata_txrx_ctrl = txrx_ctrl; |
| 7694 | |
| 7695 | return (0); |
| 7696 | } |
| 7697 | |
| 7698 | int |
| 7699 | 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 | int error, nsegs; |
| 7705 | |
| 7706 | st = malloc(sizeof(*st), M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008); |
| 7707 | sc->sc_txstats = st; |
| 7708 | |
| 7709 | /* |
| 7710 | * Create TX stats descriptor DMA stuffs |
| 7711 | */ |
| 7712 | dma_size = roundup(desc_sz * BWI_TXSTATS_NDESC, BWI_RING_ALIGN)((((desc_sz * 64)+((0x1000)-1))/(0x1000))*(0x1000)); |
| 7713 | |
| 7714 | error = bus_dmamap_create(sc->sc_dmat, dma_size, 1, dma_size, 0,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (dma_size ), (1), (dma_size), (0), (0x0001), (&st->stats_ring_dmap )) |
| 7715 | BUS_DMA_NOWAIT, &st->stats_ring_dmap)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (dma_size ), (1), (dma_size), (0), (0x0001), (&st->stats_ring_dmap )); |
| 7716 | if (error) { |
| 7717 | printf("%s: can't create txstats ring DMA mem\n", |
| 7718 | sc->sc_dev.dv_xname); |
| 7719 | return (error); |
| 7720 | } |
| 7721 | |
| 7722 | error = bus_dmamem_alloc(sc->sc_dmat, dma_size, BWI_RING_ALIGN, 0,(*(sc->sc_dmat)->_dmamem_alloc)((sc->sc_dmat), (dma_size ), (0x1000), (0), (&st->stats_ring_seg), (1), (&nsegs ), (0x0001 | 0x1000)) |
| 7723 | &st->stats_ring_seg, 1, &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO)(*(sc->sc_dmat)->_dmamem_alloc)((sc->sc_dmat), (dma_size ), (0x1000), (0), (&st->stats_ring_seg), (1), (&nsegs ), (0x0001 | 0x1000)); |
| 7724 | if (error) { |
| 7725 | printf("%s: can't allocate txstats ring DMA mem\n", |
| 7726 | sc->sc_dev.dv_xname); |
| 7727 | return (error); |
| 7728 | } |
| 7729 | |
| 7730 | error = bus_dmamem_map(sc->sc_dmat, &st->stats_ring_seg, nsegs,(*(sc->sc_dmat)->_dmamem_map)((sc->sc_dmat), (&st ->stats_ring_seg), (nsegs), (dma_size), ((caddr_t *)&st ->stats_ring), (0x0001)) |
| 7731 | dma_size, (caddr_t *)&st->stats_ring, BUS_DMA_NOWAIT)(*(sc->sc_dmat)->_dmamem_map)((sc->sc_dmat), (&st ->stats_ring_seg), (nsegs), (dma_size), ((caddr_t *)&st ->stats_ring), (0x0001)); |
| 7732 | if (error) { |
| 7733 | printf("%s: can't map txstats ring DMA mem\n", |
| 7734 | sc->sc_dev.dv_xname); |
| 7735 | return (error); |
| 7736 | } |
| 7737 | |
| 7738 | error = bus_dmamap_load(sc->sc_dmat, st->stats_ring_dmap,(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (st-> stats_ring_dmap), (st->stats_ring), (dma_size), (((void *) 0)), (0x0000)) |
| 7739 | st->stats_ring, dma_size, NULL, BUS_DMA_WAITOK)(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (st-> stats_ring_dmap), (st->stats_ring), (dma_size), (((void *) 0)), (0x0000)); |
| 7740 | if (error) { |
| 7741 | printf("%s: can't load txstats ring DMA mem\n", |
| 7742 | sc->sc_dev.dv_xname); |
| 7743 | bus_dmamem_free(sc->sc_dmat, &st->stats_ring_seg, nsegs)(*(sc->sc_dmat)->_dmamem_free)((sc->sc_dmat), (& st->stats_ring_seg), (nsegs)); |
| 7744 | return (error); |
| 7745 | } |
| 7746 | |
| 7747 | 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,((((sizeof(struct bwi_txstats) * 64)+((0x1000)-1))/(0x1000))* (0x1000)) |
| 7753 | BWI_ALIGN)((((sizeof(struct bwi_txstats) * 64)+((0x1000)-1))/(0x1000))* (0x1000)); |
| 7754 | |
| 7755 | error = bus_dmamap_create(sc->sc_dmat, dma_size, 1, dma_size, 0,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (dma_size ), (1), (dma_size), (0), (0x0001), (&st->stats_dmap)) |
| 7756 | BUS_DMA_NOWAIT, &st->stats_dmap)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (dma_size ), (1), (dma_size), (0), (0x0001), (&st->stats_dmap)); |
| 7757 | if (error) { |
| 7758 | printf("%s: can't create txstats ring DMA mem\n", |
| 7759 | sc->sc_dev.dv_xname); |
| 7760 | return (error); |
| 7761 | } |
| 7762 | error = bus_dmamem_alloc(sc->sc_dmat, dma_size, BWI_ALIGN, 0,(*(sc->sc_dmat)->_dmamem_alloc)((sc->sc_dmat), (dma_size ), (0x1000), (0), (&st->stats_seg), (1), (&nsegs), (0x0001 | 0x1000)) |
| 7763 | &st->stats_seg, 1, &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO)(*(sc->sc_dmat)->_dmamem_alloc)((sc->sc_dmat), (dma_size ), (0x1000), (0), (&st->stats_seg), (1), (&nsegs), (0x0001 | 0x1000)); |
| 7764 | if (error) { |
| 7765 | printf("%s: can't allocate txstats DMA mem\n", |
| 7766 | sc->sc_dev.dv_xname); |
| 7767 | return (error); |
| 7768 | } |
| 7769 | |
| 7770 | error = bus_dmamem_map(sc->sc_dmat, &st->stats_seg, nsegs,(*(sc->sc_dmat)->_dmamem_map)((sc->sc_dmat), (&st ->stats_seg), (nsegs), (dma_size), ((caddr_t *)&st-> stats), (0x0001)) |
| 7771 | dma_size, (caddr_t *)&st->stats, BUS_DMA_NOWAIT)(*(sc->sc_dmat)->_dmamem_map)((sc->sc_dmat), (&st ->stats_seg), (nsegs), (dma_size), ((caddr_t *)&st-> stats), (0x0001)); |
| 7772 | if (error) { |
| 7773 | printf("%s: can't map txstats DMA mem\n", sc->sc_dev.dv_xname); |
| 7774 | return (error); |
| 7775 | } |
| 7776 | |
| 7777 | error = bus_dmamap_load(sc->sc_dmat, st->stats_dmap, st->stats,(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (st-> stats_dmap), (st->stats), (dma_size), (((void *)0)), (0x0000 )) |
| 7778 | dma_size, NULL, BUS_DMA_WAITOK)(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (st-> stats_dmap), (st->stats), (dma_size), (((void *)0)), (0x0000 )); |
| 7779 | if (error) { |
| 7780 | printf("%s: can't load txstats DMA mem\n", sc->sc_dev.dv_xname); |
| 7781 | bus_dmamem_free(sc->sc_dmat, &st->stats_seg, nsegs)(*(sc->sc_dmat)->_dmamem_free)((sc->sc_dmat), (& st->stats_seg), (nsegs)); |
| 7782 | return (error); |
| 7783 | } |
| 7784 | |
| 7785 | st->stats_paddr = st->stats_dmap->dm_segs[0].ds_addr; |
| 7786 | st->stats_ctrl_base = ctrl_base; |
| 7787 | |
| 7788 | return (0); |
| 7789 | } |
| 7790 | |
| 7791 | void |
| 7792 | bwi_dma_txstats_free(struct bwi_softc *sc) |
| 7793 | { |
| 7794 | struct bwi_txstats_data *st; |
| 7795 | |
| 7796 | if (sc->sc_txstats == NULL((void *)0)) |
| 7797 | return; |
| 7798 | st = sc->sc_txstats; |
| 7799 | |
| 7800 | bus_dmamap_unload(sc->sc_dmat, st->stats_ring_dmap)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (st-> stats_ring_dmap)); |
| 7801 | bus_dmamem_free(sc->sc_dmat, &st->stats_ring_seg, 1)(*(sc->sc_dmat)->_dmamem_free)((sc->sc_dmat), (& st->stats_ring_seg), (1)); |
| 7802 | |
| 7803 | bus_dmamap_unload(sc->sc_dmat, st->stats_dmap)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (st-> stats_dmap)); |
| 7804 | bus_dmamem_free(sc->sc_dmat, &st->stats_seg, 1)(*(sc->sc_dmat)->_dmamem_free)((sc->sc_dmat), (& st->stats_seg), (1)); |
| 7805 | |
| 7806 | free(st, M_DEVBUF2, sizeof *st); |
| 7807 | } |
| 7808 | |
| 7809 | int |
| 7810 | bwi_dma_mbuf_create30(struct bwi_softc *sc) |
| 7811 | { |
| 7812 | int i, j, k, error; |
| 7813 | |
| 7814 | for (i = 0; i < BWI_TX_NRING6; ++i) { |
| 7815 | struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[i]; |
| 7816 | |
| 7817 | sc->sc_bounce_tx_data[i] = (caddr_t)km_alloc( |
| 7818 | BWI_TX_NDESC128 * MCLBYTES(1 << 11), &kv_intrsafe, |
| 7819 | &bwi_pa_mode, &kd_waitok); |
| 7820 | if (sc->sc_bounce_tx_data[i] == NULL((void *)0)) { |
| 7821 | printf(": could not allocate TX mbuf bounce buffer\n"); |
| 7822 | error = ENOMEM12; |
| 7823 | break; |
| 7824 | } |
| 7825 | |
| 7826 | for (j = 0; j < BWI_TX_NDESC128; ++j) { |
| 7827 | error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 << 11)), (1), ((1 << 11)), (0), (0x0001), (&tbd->tbd_buf [j].tb_dmap)) |
| 7828 | 1, MCLBYTES, 0, BUS_DMA_NOWAIT,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 << 11)), (1), ((1 << 11)), (0), (0x0001), (&tbd->tbd_buf [j].tb_dmap)) |
| 7829 | &tbd->tbd_buf[j].tb_dmap)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 << 11)), (1), ((1 << 11)), (0), (0x0001), (&tbd->tbd_buf [j].tb_dmap)); |
| 7830 | if (error) { |
| 7831 | printf(": cannot create TX mbuf DMA map\n"); |
| 7832 | for (k = 0; k < j; ++k) { |
| 7833 | bus_dmamap_destroy(sc->sc_dmat,(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (tbd ->tbd_buf[k].tb_dmap)) |
| 7834 | tbd->tbd_buf[k].tb_dmap)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (tbd ->tbd_buf[k].tb_dmap)); |
| 7835 | } |
| 7836 | break; |
| 7837 | } |
| 7838 | } |
| 7839 | } |
| 7840 | if (error) { |
| 7841 | bwi_dma_mbuf_destroy(sc, i, 0); |
| 7842 | for (j = 0; j < i; ++j) |
| 7843 | km_free(sc->sc_bounce_tx_data[j], BWI_TX_NDESC128, |
| 7844 | &kv_intrsafe, &bwi_pa_mode); |
| 7845 | return (error); |
| 7846 | } |
| 7847 | |
| 7848 | for (i = 0; i < BWI_TX_NRING6; ++i) { |
| 7849 | struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[i]; |
| 7850 | |
| 7851 | for (j = 0; j < BWI_TX_NDESC128; ++j) { |
| 7852 | struct bwi_txbuf *tb = &tbd->tbd_buf[j]; |
| 7853 | |
| 7854 | error = bus_dmamap_load(sc->sc_dmat, tb->tb_dmap,(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (tb-> tb_dmap), (sc->sc_bounce_tx_data[i] + ((1 << 11) * j )), ((1 << 11)), (((void *)0)), (0x0001)) |
| 7855 | sc->sc_bounce_tx_data[i] + (MCLBYTES * j),(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (tb-> tb_dmap), (sc->sc_bounce_tx_data[i] + ((1 << 11) * j )), ((1 << 11)), (((void *)0)), (0x0001)) |
| 7856 | MCLBYTES, NULL, BUS_DMA_NOWAIT)(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (tb-> tb_dmap), (sc->sc_bounce_tx_data[i] + ((1 << 11) * j )), ((1 << 11)), (((void *)0)), (0x0001)); |
| 7857 | if (error) { |
| 7858 | printf(": cannot create TX mbuf DMA map\n"); |
| 7859 | for (k = 0; k < j; ++k) { |
| 7860 | bus_dmamap_destroy(sc->sc_dmat,(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (tbd ->tbd_buf[k].tb_dmap)) |
| 7861 | tbd->tbd_buf[k].tb_dmap)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (tbd ->tbd_buf[k].tb_dmap)); |
| 7862 | } |
| 7863 | break; |
| 7864 | } |
| 7865 | } |
| 7866 | } |
| 7867 | if (error) { |
| 7868 | bwi_dma_mbuf_destroy(sc, BWI_TX_NRING6, 0); |
| 7869 | for (i = 0; i < BWI_TX_NRING6; ++i) |
| 7870 | km_free(sc->sc_bounce_tx_data[i], BWI_TX_NDESC128, |
| 7871 | &kv_intrsafe, &bwi_pa_mode); |
| 7872 | return (error); |
| 7873 | } |
| 7874 | |
| 7875 | sc->sc_bounce_rx_data = (caddr_t)km_alloc(BWI_RX_NDESC64 * MCLBYTES(1 << 11), |
| 7876 | &kv_intrsafe, &bwi_pa_mode, &kd_waitok); |
| 7877 | if (sc->sc_bounce_rx_data == NULL((void *)0)) { |
| 7878 | printf(": could not allocate RX mbuf bounce buffer\n"); |
| 7879 | bwi_dma_mbuf_destroy(sc, BWI_TX_NRING6, 0); |
| 7880 | for (i = 0; i < BWI_TX_NRING6; ++i) |
| 7881 | km_free(sc->sc_bounce_tx_data[i], BWI_TX_NDESC128, |
| 7882 | &kv_intrsafe, &bwi_pa_mode); |
| 7883 | return (ENOMEM12); |
| 7884 | } |
| 7885 | |
| 7886 | for (i = 0; i < BWI_RX_NDESC64; ++i) { |
| 7887 | error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 << 11)), (1), ((1 << 11)), (0), (0x0001), (&sc->sc_rx_bdata .rbd_buf[i].rb_dmap)) |
| 7888 | MCLBYTES, 0, BUS_DMA_NOWAIT,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 << 11)), (1), ((1 << 11)), (0), (0x0001), (&sc->sc_rx_bdata .rbd_buf[i].rb_dmap)) |
| 7889 | &sc->sc_rx_bdata.rbd_buf[i].rb_dmap)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 << 11)), (1), ((1 << 11)), (0), (0x0001), (&sc->sc_rx_bdata .rbd_buf[i].rb_dmap)); |
| 7890 | if (error) { |
| 7891 | printf(": cannot create RX mbuf DMA map\n"); |
| 7892 | for (j = 0; j < i; ++j) { |
| 7893 | bus_dmamap_destroy(sc->sc_dmat,(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (sc ->sc_rx_bdata.rbd_buf[j].rb_dmap)) |
| 7894 | sc->sc_rx_bdata.rbd_buf[j].rb_dmap)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (sc ->sc_rx_bdata.rbd_buf[j].rb_dmap)); |
| 7895 | } |
| 7896 | break; |
| 7897 | } |
| 7898 | } |
| 7899 | if (error) { |
| 7900 | bwi_dma_mbuf_destroy(sc, BWI_TX_NRING6, 0); |
| 7901 | for (i = 0; i < BWI_TX_NRING6; ++i) |
| 7902 | km_free(sc->sc_bounce_tx_data[i], BWI_TX_NDESC128, |
| 7903 | &kv_intrsafe, &bwi_pa_mode); |
| 7904 | km_free(sc->sc_bounce_rx_data, BWI_RX_NDESC64 * MCLBYTES(1 << 11), |
| 7905 | &kv_intrsafe, &bwi_pa_mode); |
| 7906 | return (error); |
| 7907 | } |
| 7908 | |
| 7909 | for (i = 0; i < BWI_RX_NDESC64; ++i) { |
| 7910 | error = bwi_newbuf30(sc, i, 1); |
| 7911 | if (error) { |
| 7912 | printf(": cannot create RX mbuf DMA map\n"); |
| 7913 | break; |
| 7914 | } |
| 7915 | } |
| 7916 | if (error) { |
| 7917 | bwi_dma_mbuf_destroy(sc, BWI_TX_NRING6, 1); |
| 7918 | for (i = 0; i < BWI_TX_NRING6; ++i) |
| 7919 | km_free(sc->sc_bounce_tx_data[i], BWI_TX_NDESC128, |
| 7920 | &kv_intrsafe, &bwi_pa_mode); |
| 7921 | km_free(sc->sc_bounce_rx_data, BWI_RX_NDESC64 * MCLBYTES(1 << 11), |
| 7922 | &kv_intrsafe, &bwi_pa_mode); |
| 7923 | return (error); |
| 7924 | } |
| 7925 | |
| 7926 | return (0); |
| 7927 | } |
| 7928 | |
| 7929 | int |
| 7930 | bwi_dma_mbuf_create(struct bwi_softc *sc) |
| 7931 | { |
| 7932 | 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 | for (i = 0; i < BWI_TX_NRING6; ++i) { |
| 7941 | struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[i]; |
| 7942 | |
| 7943 | for (j = 0; j < BWI_TX_NDESC128; ++j) { |
| 7944 | error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 << 11)), (1), ((1 << 11)), (0), (0x0001), (&tbd->tbd_buf [j].tb_dmap)) |
| 7945 | 0, BUS_DMA_NOWAIT, &tbd->tbd_buf[j].tb_dmap)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 << 11)), (1), ((1 << 11)), (0), (0x0001), (&tbd->tbd_buf [j].tb_dmap)); |
| 7946 | if (error) { |
| 7947 | printf( |
| 7948 | "%s: can't create %dth tbd, %dth DMA map\n", |
| 7949 | sc->sc_dev.dv_xname, i, j); |
| 7950 | ntx = i; |
| 7951 | for (k = 0; k < j; ++k) { |
| 7952 | bus_dmamap_destroy(sc->sc_dmat,(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (tbd ->tbd_buf[k].tb_dmap)) |
| 7953 | tbd->tbd_buf[k].tb_dmap)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (tbd ->tbd_buf[k].tb_dmap)); |
| 7954 | } |
| 7955 | goto fail; |
| 7956 | } |
| 7957 | } |
| 7958 | } |
| 7959 | ntx = BWI_TX_NRING6; |
| 7960 | |
| 7961 | /* |
| 7962 | * Create RX mbuf DMA map and a spare DMA map |
| 7963 | */ |
| 7964 | error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 << 11)), (1), ((1 << 11)), (0), (0x0001), (&rbd->rbd_tmp_dmap )) |
| 7965 | BUS_DMA_NOWAIT, &rbd->rbd_tmp_dmap)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 << 11)), (1), ((1 << 11)), (0), (0x0001), (&rbd->rbd_tmp_dmap )); |
| 7966 | if (error) { |
| 7967 | printf("%s: can't create spare RX buf DMA map\n", |
| 7968 | sc->sc_dev.dv_xname); |
| 7969 | goto fail; |
| 7970 | } |
| 7971 | |
| 7972 | for (j = 0; j < BWI_RX_NDESC64; ++j) { |
| 7973 | error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 << 11)), (1), ((1 << 11)), (0), (0x0001), (&rbd->rbd_buf [j].rb_dmap)) |
| 7974 | BUS_DMA_NOWAIT, &rbd->rbd_buf[j].rb_dmap)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 << 11)), (1), ((1 << 11)), (0), (0x0001), (&rbd->rbd_buf [j].rb_dmap)); |
| 7975 | if (error) { |
| 7976 | printf("%s: can't create %dth RX buf DMA map\n", |
| 7977 | sc->sc_dev.dv_xname, j); |
| 7978 | |
| 7979 | for (k = 0; k < j; ++k) { |
| 7980 | bus_dmamap_destroy(sc->sc_dmat,(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (rbd ->rbd_buf[k].rb_dmap)) |
| 7981 | rbd->rbd_buf[k].rb_dmap)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (rbd ->rbd_buf[k].rb_dmap)); |
| 7982 | } |
| 7983 | bus_dmamap_destroy(sc->sc_dmat,(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (rbd ->rbd_tmp_dmap)) |
| 7984 | rbd->rbd_tmp_dmap)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (rbd ->rbd_tmp_dmap)); |
| 7985 | goto fail; |
| 7986 | } |
| 7987 | } |
| 7988 | |
| 7989 | return 0; |
| 7990 | fail: |
| 7991 | bwi_dma_mbuf_destroy(sc, ntx, 0); |
| 7992 | |
| 7993 | return (error); |
| 7994 | } |
| 7995 | |
| 7996 | void |
| 7997 | bwi_dma_mbuf_destroy(struct bwi_softc *sc, int ntx, int nrx) |
| 7998 | { |
| 7999 | struct ieee80211com *ic = &sc->sc_ic; |
| 8000 | int i, j; |
| 8001 | |
| 8002 | for (i = 0; i < ntx; ++i) { |
| 8003 | struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[i]; |
| 8004 | |
| 8005 | for (j = 0; j < BWI_TX_NDESC128; ++j) { |
| 8006 | struct bwi_txbuf *tb = &tbd->tbd_buf[j]; |
| 8007 | |
| 8008 | if (tb->tb_mbuf != NULL((void *)0)) { |
| 8009 | bus_dmamap_unload(sc->sc_dmat,(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (tb-> tb_dmap)) |
| 8010 | tb->tb_dmap)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (tb-> tb_dmap)); |
| 8011 | m_freem(tb->tb_mbuf); |
| 8012 | } |
| 8013 | if (tb->tb_ni != NULL((void *)0)) |
| 8014 | ieee80211_release_node(ic, tb->tb_ni); |
| 8015 | bus_dmamap_destroy(sc->sc_dmat, tb->tb_dmap)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (tb ->tb_dmap)); |
| 8016 | } |
| 8017 | } |
| 8018 | |
| 8019 | if (nrx) { |
| 8020 | struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata; |
| 8021 | |
| 8022 | bus_dmamap_destroy(sc->sc_dmat, rbd->rbd_tmp_dmap)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (rbd ->rbd_tmp_dmap)); |
| 8023 | for (j = 0; j < BWI_RX_NDESC64; ++j) { |
| 8024 | struct bwi_rxbuf *rb = &rbd->rbd_buf[j]; |
| 8025 | |
| 8026 | if (rb->rb_mbuf != NULL((void *)0)) { |
| 8027 | bus_dmamap_unload(sc->sc_dmat,(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (rb-> rb_dmap)) |
| 8028 | rb->rb_dmap)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (rb-> rb_dmap)); |
| 8029 | m_freem(rb->rb_mbuf); |
| 8030 | } |
| 8031 | bus_dmamap_destroy(sc->sc_dmat, rb->rb_dmap)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (rb ->rb_dmap)); |
| 8032 | } |
| 8033 | } |
| 8034 | } |
| 8035 | |
| 8036 | void |
| 8037 | bwi_enable_intrs(struct bwi_softc *sc, uint32_t enable_intrs) |
| 8038 | { |
| 8039 | CSR_SETBITS_4(sc, BWI_MAC_INTR_MASK, enable_intrs)((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x0000012c))), ((((((sc))->sc_mem_bt)->read_4((((sc)) ->sc_mem_bh), (((0x0000012c))))) | (enable_intrs))))); |
| 8040 | } |
| 8041 | |
| 8042 | void |
| 8043 | bwi_disable_intrs(struct bwi_softc *sc, uint32_t disable_intrs) |
| 8044 | { |
| 8045 | CSR_CLRBITS_4(sc, BWI_MAC_INTR_MASK, disable_intrs)((((sc))->sc_mem_bt)->write_4((((sc))->sc_mem_bh), ( ((0x0000012c))), ((((((sc))->sc_mem_bt)->read_4((((sc)) ->sc_mem_bh), (((0x0000012c))))) & ~(disable_intrs)))) ); |
| 8046 | } |
| 8047 | |
| 8048 | int |
| 8049 | 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 | KASSERT(ring_idx < BWI_TX_NRING)((ring_idx < 6) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c" , 8055, "ring_idx < BWI_TX_NRING")); |
| 8056 | rd = &sc->sc_tx_rdata[ring_idx]; |
| 8057 | tbd = &sc->sc_tx_bdata[ring_idx]; |
| 8058 | |
| 8059 | tbd->tbd_idx = 0; |
| 8060 | tbd->tbd_used = 0; |
| 8061 | |
| 8062 | bzero(rd->rdata_desc, sizeof(struct bwi_desc32) * BWI_TX_NDESC)__builtin_bzero((rd->rdata_desc), (sizeof(struct bwi_desc32 ) * 128)); |
| 8063 | bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rd-> rdata_dmap), (0), (rd->rdata_dmap->dm_mapsize), (0x04)) |
| 8064 | rd->rdata_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rd-> rdata_dmap), (0), (rd->rdata_dmap->dm_mapsize), (0x04)); |
| 8065 | |
| 8066 | addr_lo = __SHIFTOUT(rd->rdata_paddr, BWI_TXRX32_RINGINFO_ADDR_MASK)(((rd->rdata_paddr) & (0x3fffffff)) / ((((0x3fffffff) - 1) & (0x3fffffff)) ^ (0x3fffffff))); |
| 8067 | addr_hi = __SHIFTOUT(rd->rdata_paddr, BWI_TXRX32_RINGINFO_FUNC_MASK)(((rd->rdata_paddr) & (0xc0000000)) / ((((0xc0000000) - 1) & (0xc0000000)) ^ (0xc0000000))); |
| 8068 | |
| 8069 | val = __SHIFTIN(addr_lo, BWI_TXRX32_RINGINFO_ADDR_MASK)((addr_lo) * ((((0x3fffffff) - 1) & (0x3fffffff)) ^ (0x3fffffff ))) | |
| 8070 | __SHIFTIN(BWI_TXRX32_RINGINFO_FUNC_TXRX,((0x1) * ((((0xc0000000) - 1) & (0xc0000000)) ^ (0xc0000000 ))) |
| 8071 | BWI_TXRX32_RINGINFO_FUNC_MASK)((0x1) * ((((0xc0000000) - 1) & (0xc0000000)) ^ (0xc0000000 ))); |
| 8072 | CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_RINGINFO, val)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((rd-> rdata_txrx_ctrl + 0x4)), ((val)))); |
| 8073 | |
| 8074 | val = __SHIFTIN(addr_hi, BWI_TXRX32_CTRL_ADDRHI_MASK)((addr_hi) * ((((0x00030000) - 1) & (0x00030000)) ^ (0x00030000 ))) | |
| 8075 | BWI_TXRX32_CTRL_ENABLE(1 << 0); |
| 8076 | CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_CTRL, val)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((rd-> rdata_txrx_ctrl + 0x0)), ((val)))); |
| 8077 | |
| 8078 | return (0); |
| 8079 | } |
| 8080 | |
| 8081 | void |
| 8082 | 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 | addr_lo = __SHIFTOUT(paddr, BWI_TXRX32_RINGINFO_ADDR_MASK)(((paddr) & (0x3fffffff)) / ((((0x3fffffff) - 1) & (0x3fffffff )) ^ (0x3fffffff))); |
| 8088 | addr_hi = __SHIFTOUT(paddr, BWI_TXRX32_RINGINFO_FUNC_MASK)(((paddr) & (0xc0000000)) / ((((0xc0000000) - 1) & (0xc0000000 )) ^ (0xc0000000))); |
| 8089 | |
| 8090 | val = __SHIFTIN(addr_lo, BWI_TXRX32_RINGINFO_ADDR_MASK)((addr_lo) * ((((0x3fffffff) - 1) & (0x3fffffff)) ^ (0x3fffffff ))) | |
| 8091 | __SHIFTIN(BWI_TXRX32_RINGINFO_FUNC_TXRX,((0x1) * ((((0xc0000000) - 1) & (0xc0000000)) ^ (0xc0000000 ))) |
| 8092 | BWI_TXRX32_RINGINFO_FUNC_MASK)((0x1) * ((((0xc0000000) - 1) & (0xc0000000)) ^ (0xc0000000 ))); |
| 8093 | CSR_WRITE_4(sc, ctrl_base + BWI_RX32_RINGINFO, val)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((ctrl_base + 0x14)), ((val)))); |
| 8094 | |
| 8095 | val = __SHIFTIN(hdr_size, BWI_RX32_CTRL_HDRSZ_MASK)((hdr_size) * ((((0x00fe) - 1) & (0x00fe)) ^ (0x00fe))) | |
| 8096 | __SHIFTIN(addr_hi, BWI_TXRX32_CTRL_ADDRHI_MASK)((addr_hi) * ((((0x00030000) - 1) & (0x00030000)) ^ (0x00030000 ))) | |
| 8097 | BWI_TXRX32_CTRL_ENABLE(1 << 0); |
| 8098 | CSR_WRITE_4(sc, ctrl_base + BWI_RX32_CTRL, val)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((ctrl_base + 0x10)), ((val)))); |
| 8099 | |
| 8100 | CSR_WRITE_4(sc, ctrl_base + BWI_RX32_INDEX,(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((ctrl_base + 0x18)), (((ndesc - 1) * sizeof(struct bwi_desc32))))) |
| 8101 | (ndesc - 1) * sizeof(struct bwi_desc32))(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((ctrl_base + 0x18)), (((ndesc - 1) * sizeof(struct bwi_desc32))))); |
| 8102 | } |
| 8103 | |
| 8104 | int |
| 8105 | bwi_init_rx_ring32(struct bwi_softc *sc) |
| 8106 | { |
| 8107 | struct bwi_ring_data *rd = &sc->sc_rx_rdata; |
| 8108 | int i, error; |
| 8109 | |
| 8110 | sc->sc_rx_bdata.rbd_idx = 0; |
| 8111 | bzero(rd->rdata_desc, sizeof(struct bwi_desc32) * BWI_RX_NDESC)__builtin_bzero((rd->rdata_desc), (sizeof(struct bwi_desc32 ) * 64)); |
| 8112 | |
| 8113 | for (i = 0; i < BWI_RX_NDESC64; ++i) { |
| 8114 | error = sc->sc_newbuf(sc, i, 1); |
| 8115 | if (error) { |
| 8116 | printf("%s: can't allocate %dth RX buffer\n", |
| 8117 | sc->sc_dev.dv_xname, i); |
| 8118 | return (error); |
| 8119 | } |
| 8120 | } |
| 8121 | bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rd-> rdata_dmap), (0), (rd->rdata_dmap->dm_mapsize), (0x04)) |
| 8122 | rd->rdata_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rd-> rdata_dmap), (0), (rd->rdata_dmap->dm_mapsize), (0x04)); |
| 8123 | |
| 8124 | bwi_init_rxdesc_ring32(sc, rd->rdata_txrx_ctrl, rd->rdata_paddr, |
| 8125 | sizeof(struct bwi_rxbuf_hdr), BWI_RX_NDESC64); |
| 8126 | return (0); |
| 8127 | } |
| 8128 | |
| 8129 | int |
| 8130 | bwi_init_txstats32(struct bwi_softc *sc) |
| 8131 | { |
| 8132 | struct bwi_txstats_data *st = sc->sc_txstats; |
| 8133 | bus_addr_t stats_paddr; |
| 8134 | int i; |
| 8135 | |
| 8136 | bzero(st->stats, BWI_TXSTATS_NDESC * sizeof(struct bwi_txstats))__builtin_bzero((st->stats), (64 * sizeof(struct bwi_txstats ))); |
| 8137 | bus_dmamap_sync(sc->sc_dmat, st->stats_dmap, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (st-> stats_dmap), (0), (st->stats_dmap->dm_mapsize), (0x04)) |
| 8138 | st->stats_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (st-> stats_dmap), (0), (st->stats_dmap->dm_mapsize), (0x04)); |
| 8139 | |
| 8140 | st->stats_idx = 0; |
| 8141 | |
| 8142 | stats_paddr = st->stats_paddr; |
| 8143 | for (i = 0; i < BWI_TXSTATS_NDESC64; ++i) { |
| 8144 | bwi_setup_desc32(sc, st->stats_ring, BWI_TXSTATS_NDESC64, i, |
| 8145 | stats_paddr, sizeof(struct bwi_txstats), 0); |
| 8146 | stats_paddr += sizeof(struct bwi_txstats); |
| 8147 | } |
| 8148 | bus_dmamap_sync(sc->sc_dmat, st->stats_ring_dmap, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (st-> stats_ring_dmap), (0), (st->stats_ring_dmap->dm_mapsize ), (0x04)) |
| 8149 | st->stats_ring_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (st-> stats_ring_dmap), (0), (st->stats_ring_dmap->dm_mapsize ), (0x04)); |
| 8150 | |
| 8151 | bwi_init_rxdesc_ring32(sc, st->stats_ctrl_base, |
| 8152 | st->stats_ring_paddr, 0, BWI_TXSTATS_NDESC64); |
| 8153 | |
| 8154 | return (0); |
| 8155 | } |
| 8156 | |
| 8157 | void |
| 8158 | bwi_setup_rx_desc32(struct bwi_softc *sc, int buf_idx, bus_addr_t paddr, |
| 8159 | int buf_len) |
| 8160 | { |
| 8161 | struct bwi_ring_data *rd = &sc->sc_rx_rdata; |
| 8162 | |
| 8163 | KASSERT(buf_idx < BWI_RX_NDESC)((buf_idx < 64) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c" , 8163, "buf_idx < BWI_RX_NDESC")); |
| 8164 | bwi_setup_desc32(sc, rd->rdata_desc, BWI_RX_NDESC64, buf_idx, |
| 8165 | paddr, buf_len, 0); |
| 8166 | } |
| 8167 | |
| 8168 | void |
| 8169 | 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 | KASSERT(buf_idx < BWI_TX_NDESC)((buf_idx < 128) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c" , 8172, "buf_idx < BWI_TX_NDESC")); |
| 8173 | bwi_setup_desc32(sc, rd->rdata_desc, BWI_TX_NDESC128, buf_idx, |
| 8174 | paddr, buf_len, 1); |
| 8175 | } |
| 8176 | |
| 8177 | int |
| 8178 | bwi_newbuf30(struct bwi_softc *sc, int buf_idx, int init) |
| 8179 | { |
| 8180 | struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata; |
| 8181 | struct bwi_rxbuf *rb = &rbd->rbd_buf[buf_idx]; |
| 8182 | struct mbuf *m; |
| 8183 | struct bwi_rxbuf_hdr *hdr; |
| 8184 | int error; |
| 8185 | |
| 8186 | KASSERT(buf_idx < BWI_RX_NDESC)((buf_idx < 64) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c" , 8186, "buf_idx < BWI_RX_NDESC")); |
| 8187 | |
| 8188 | /* Create host-side mbuf. */ |
| 8189 | MGETHDR(m, init ? M_WAITOK : M_NOWAIT, MT_DATA)m = m_gethdr((init ? 0x0001 : 0x0002), (1)); |
| 8190 | if (m == NULL((void *)0)) |
| 8191 | return (ENOBUFS55); |
| 8192 | MCLGET(m, init ? M_WAITOK : M_NOWAIT)(void) m_clget((m), (init ? 0x0001 : 0x0002), (1 << 11) ); |
| 8193 | if (m == NULL((void *)0)) |
| 8194 | return (ENOBUFS55); |
| 8195 | m->m_lenm_hdr.mh_len = m->m_pkthdrM_dat.MH.MH_pkthdr.len = MCLBYTES(1 << 11); |
| 8196 | |
| 8197 | if (init) { |
| 8198 | /* Load device-side RX DMA buffer. */ |
| 8199 | error = bus_dmamap_load(sc->sc_dmat, rb->rb_dmap,(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (rb-> rb_dmap), (sc->sc_bounce_rx_data + ((1 << 11) * buf_idx )), ((1 << 11)), (((void *)0)), (0x0000)) |
| 8200 | sc->sc_bounce_rx_data + (MCLBYTES * buf_idx),(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (rb-> rb_dmap), (sc->sc_bounce_rx_data + ((1 << 11) * buf_idx )), ((1 << 11)), (((void *)0)), (0x0000)) |
| 8201 | MCLBYTES, NULL, BUS_DMA_WAITOK)(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (rb-> rb_dmap), (sc->sc_bounce_rx_data + ((1 << 11) * buf_idx )), ((1 << 11)), (((void *)0)), (0x0000)); |
| 8202 | if (error) { |
| 8203 | m_freem(m); |
| 8204 | return (error); |
| 8205 | } |
| 8206 | } |
| 8207 | |
| 8208 | rb->rb_mbuf = m; |
| 8209 | rb->rb_paddr = rb->rb_dmap->dm_segs[0].ds_addr; |
| 8210 | |
| 8211 | /* |
| 8212 | * Clear RX buf header |
| 8213 | */ |
| 8214 | hdr = (struct bwi_rxbuf_hdr *)(sc->sc_bounce_rx_data + |
| 8215 | (MCLBYTES(1 << 11) * buf_idx)); |
| 8216 | bzero(hdr, sizeof(*hdr))__builtin_bzero((hdr), (sizeof(*hdr))); |
| 8217 | bus_dmamap_sync(sc->sc_dmat, rb->rb_dmap, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rb-> rb_dmap), (0), (rb->rb_dmap->dm_mapsize), (0x04)) |
| 8218 | rb->rb_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rb-> rb_dmap), (0), (rb->rb_dmap->dm_mapsize), (0x04)); |
| 8219 | |
| 8220 | /* |
| 8221 | * Setup RX buf descriptor |
| 8222 | */ |
| 8223 | sc->sc_setup_rxdesc(sc, buf_idx, rb->rb_paddr, |
| 8224 | m->m_lenm_hdr.mh_len - sizeof(*hdr)); |
| 8225 | |
| 8226 | return (0); |
| 8227 | } |
| 8228 | |
| 8229 | int |
| 8230 | bwi_newbuf(struct bwi_softc *sc, int buf_idx, int init) |
| 8231 | { |
| 8232 | struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata; |
| 8233 | 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 | KASSERT(buf_idx < BWI_RX_NDESC)((buf_idx < 64) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c" , 8240, "buf_idx < BWI_RX_NDESC")); |
| 8241 | |
| 8242 | MGETHDR(m, init ? M_WAITOK : M_DONTWAIT, MT_DATA)m = m_gethdr((init ? 0x0001 : 0x0002), (1)); |
| 8243 | if (m == NULL((void *)0)) |
| 8244 | return (ENOBUFS55); |
| 8245 | MCLGET(m, init ? M_WAITOK : M_DONTWAIT)(void) m_clget((m), (init ? 0x0001 : 0x0002), (1 << 11) ); |
| 8246 | if (m == NULL((void *)0)) { |
| 8247 | error = ENOBUFS55; |
| 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 | if (init) |
| 8255 | return error; |
| 8256 | else |
| 8257 | goto back; |
| 8258 | } |
| 8259 | m->m_lenm_hdr.mh_len = m->m_pkthdrM_dat.MH.MH_pkthdr.len = MCLBYTES(1 << 11); |
| 8260 | |
| 8261 | /* |
| 8262 | * Try to load RX buf into temporary DMA map |
| 8263 | */ |
| 8264 | error = bus_dmamap_load_mbuf(sc->sc_dmat, rbd->rbd_tmp_dmap, m,(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), ( rbd->rbd_tmp_dmap), (m), (init ? 0x0000 : 0x0001)) |
| 8265 | init ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT)(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), ( rbd->rbd_tmp_dmap), (m), (init ? 0x0000 : 0x0001)); |
| 8266 | if (error) { |
| 8267 | m_freem(m); |
| 8268 | |
| 8269 | /* |
| 8270 | * See the comment above |
| 8271 | */ |
| 8272 | if (init) |
| 8273 | return error; |
| 8274 | else |
| 8275 | goto back; |
| 8276 | } |
| 8277 | |
| 8278 | if (!init) |
| 8279 | bus_dmamap_unload(sc->sc_dmat, rxbuf->rb_dmap)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (rxbuf ->rb_dmap)); |
| 8280 | rxbuf->rb_mbuf = m; |
| 8281 | |
| 8282 | /* |
| 8283 | * Swap RX buf's DMA map with the loaded temporary one |
| 8284 | */ |
| 8285 | map = rxbuf->rb_dmap; |
| 8286 | rxbuf->rb_dmap = rbd->rbd_tmp_dmap; |
| 8287 | rbd->rbd_tmp_dmap = map; |
| 8288 | paddr = rxbuf->rb_dmap->dm_segs[0].ds_addr; |
| 8289 | rxbuf->rb_paddr = paddr; |
| 8290 | |
| 8291 | back: |
| 8292 | /* |
| 8293 | * Clear RX buf header |
| 8294 | */ |
| 8295 | hdr = mtod(rxbuf->rb_mbuf, struct bwi_rxbuf_hdr *)((struct bwi_rxbuf_hdr *)((rxbuf->rb_mbuf)->m_hdr.mh_data )); |
| 8296 | bzero(hdr, sizeof(*hdr))__builtin_bzero((hdr), (sizeof(*hdr))); |
| 8297 | bus_dmamap_sync(sc->sc_dmat, rxbuf->rb_dmap, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rxbuf ->rb_dmap), (0), (rxbuf->rb_dmap->dm_mapsize), (0x04 )) |
| 8298 | rxbuf->rb_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rxbuf ->rb_dmap), (0), (rxbuf->rb_dmap->dm_mapsize), (0x04 )); |
| 8299 | |
| 8300 | /* |
| 8301 | * Setup RX buf descriptor |
| 8302 | */ |
| 8303 | sc->sc_setup_rxdesc(sc, buf_idx, rxbuf->rb_paddr, |
| 8304 | rxbuf->rb_mbuf->m_lenm_hdr.mh_len - sizeof(*hdr)); |
| 8305 | return error; |
| 8306 | } |
| 8307 | |
| 8308 | void |
| 8309 | bwi_set_addr_filter(struct bwi_softc *sc, uint16_t addr_ofs, |
| 8310 | const uint8_t *addr) |
| 8311 | { |
| 8312 | int i; |
| 8313 | |
| 8314 | CSR_WRITE_2(sc, BWI_ADDR_FILTER_CTRL,(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x0420 )), ((0x0020 | addr_ofs)))) |
| 8315 | BWI_ADDR_FILTER_CTRL_SET | addr_ofs)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x0420 )), ((0x0020 | addr_ofs)))); |
| 8316 | |
| 8317 | for (i = 0; i < (IEEE80211_ADDR_LEN6 / 2); ++i) { |
| 8318 | uint16_t addr_val; |
| 8319 | |
| 8320 | addr_val = (uint16_t)addr[i * 2] | |
| 8321 | (((uint16_t)addr[(i * 2) + 1]) << 8); |
| 8322 | CSR_WRITE_2(sc, BWI_ADDR_FILTER_DATA, addr_val)(((sc)->sc_mem_bt)->write_2(((sc)->sc_mem_bh), ((0x422 )), ((addr_val)))); |
| 8323 | } |
| 8324 | } |
| 8325 | |
| 8326 | int |
| 8327 | bwi_set_chan(struct bwi_softc *sc, uint8_t chan) |
| 8328 | { |
| 8329 | struct bwi_mac *mac; |
| 8330 | |
| 8331 | KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC)((sc->sc_cur_regwin->rw_type == 0x812) ? (void)0 : __assert ("diagnostic ", "/usr/src/sys/dev/ic/bwi.c", 8331, "sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC" )); |
| 8332 | mac = (struct bwi_mac *)sc->sc_cur_regwin; |
| 8333 | |
| 8334 | bwi_rf_set_chan(mac, chan, 0); |
| 8335 | |
| 8336 | return (0); |
| 8337 | } |
| 8338 | |
| 8339 | void |
| 8340 | bwi_next_scan(void *xsc) |
| 8341 | { |
| 8342 | struct bwi_softc *sc = xsc; |
| 8343 | struct ieee80211com *ic = &sc->sc_ic; |
| 8344 | struct ifnet *ifp = &ic->ic_ific_ac.ac_if; |
| 8345 | int s; |
| 8346 | |
| 8347 | s = splnet()splraise(0x4); |
| 8348 | |
| 8349 | if (ic->ic_state == IEEE80211_S_SCAN) |
| 8350 | ieee80211_next_scan(ifp); |
| 8351 | |
| 8352 | splx(s)spllower(s); |
| 8353 | } |
| 8354 | |
| 8355 | int |
| 8356 | bwi_rxeof(struct bwi_softc *sc, int end_idx) |
| 8357 | { |
| 8358 | struct mbuf_list ml = MBUF_LIST_INITIALIZER(){ ((void *)0), ((void *)0), 0 }; |
| 8359 | struct bwi_ring_data *rd = &sc->sc_rx_rdata; |
| 8360 | struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata; |
| 8361 | struct ieee80211com *ic = &sc->sc_ic; |
| 8362 | struct ifnet *ifp = &ic->ic_ific_ac.ac_if; |
| 8363 | int idx, rx_data = 0; |
| 8364 | |
| 8365 | idx = rbd->rbd_idx; |
| 8366 | while (idx != end_idx) { |
| 8367 | struct bwi_rxbuf *rb = &rbd->rbd_buf[idx]; |
| 8368 | struct bwi_rxbuf_hdr *hdr; |
| 8369 | struct ieee80211_frame *wh; |
| 8370 | struct ieee80211_rxinfo rxi; |
| 8371 | struct ieee80211_node *ni; |
| 8372 | struct mbuf *m; |
| 8373 | uint32_t plcp; |
| 8374 | uint16_t flags2; |
| 8375 | int buflen, wh_ofs, hdr_extra, rssi, type, rate; |
| 8376 | |
| 8377 | bus_dmamap_sync(sc->sc_dmat, rb->rb_dmap, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rb-> rb_dmap), (0), (rb->rb_dmap->dm_mapsize), (0x02)) |
| 8378 | rb->rb_dmap->dm_mapsize, BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rb-> rb_dmap), (0), (rb->rb_dmap->dm_mapsize), (0x02)); |
| 8379 | |
| 8380 | if (sc->sc_bus_space == BWI_BUS_SPACE_30BIT) { |
| 8381 | /* Bounce for 30bit devices. */ |
| 8382 | if (m_copyback(rb->rb_mbuf, 0, MCLBYTES(1 << 11), |
| 8383 | sc->sc_bounce_rx_data + (MCLBYTES(1 << 11) * idx), |
| 8384 | M_NOWAIT0x0002) == ENOBUFS55) { |
| 8385 | ifp->if_ierrorsif_data.ifi_ierrors++; |
| 8386 | goto next; |
| 8387 | } |
| 8388 | } |
| 8389 | |
| 8390 | m = rb->rb_mbuf; |
| 8391 | |
| 8392 | if (sc->sc_newbuf(sc, idx, 0)) { |
| 8393 | ifp->if_ierrorsif_data.ifi_ierrors++; |
| 8394 | goto next; |
| 8395 | } |
| 8396 | |
| 8397 | hdr = mtod(m, struct bwi_rxbuf_hdr *)((struct bwi_rxbuf_hdr *)((m)->m_hdr.mh_data)); |
| 8398 | flags2 = letoh16(hdr->rxh_flags2)((__uint16_t)(hdr->rxh_flags2)); |
| 8399 | |
| 8400 | hdr_extra = 0; |
| 8401 | if (flags2 & BWI_RXH_F2_TYPE2FRAME(1 << 2)) |
| 8402 | hdr_extra = 2; |
| 8403 | wh_ofs = hdr_extra + 6; |
| 8404 | |
| 8405 | buflen = letoh16(hdr->rxh_buflen)((__uint16_t)(hdr->rxh_buflen)); |
| 8406 | if (buflen <= wh_ofs) { |
| 8407 | printf("%s: zero length data, hdr_extra %d\n", |
| 8408 | sc->sc_dev.dv_xname, hdr_extra); |
| 8409 | ifp->if_ierrorsif_data.ifi_ierrors++; |
| 8410 | m_freem(m); |
| 8411 | goto next; |
| 8412 | } |
| 8413 | |
| 8414 | bcopy((uint8_t *)(hdr + 1) + hdr_extra, &plcp, sizeof(plcp)); |
| 8415 | rssi = bwi_calc_rssi(sc, hdr); |
| 8416 | |
| 8417 | m->m_lenm_hdr.mh_len = m->m_pkthdrM_dat.MH.MH_pkthdr.len = buflen + sizeof(*hdr); |
| 8418 | m_adj(m, sizeof(*hdr) + wh_ofs); |
| 8419 | |
| 8420 | if (htole16(hdr->rxh_flags1)((__uint16_t)(hdr->rxh_flags1)) & BWI_RXH_F1_OFDM(1 << 0)) |
| 8421 | rate = bwi_plcp2rate(plcp, IEEE80211_MODE_11G); |
| 8422 | else |
| 8423 | rate = bwi_plcp2rate(plcp, IEEE80211_MODE_11B); |
| 8424 | |
| 8425 | #if NBPFILTER1 > 0 |
| 8426 | /* RX radio tap */ |
| 8427 | if (sc->sc_drvbpf != NULL((void *)0)) { |
| 8428 | struct mbuf mb; |
| 8429 | struct bwi_rx_radiotap_hdr *tap = &sc->sc_rxtapsc_rxtapu.th; |
| 8430 | |
| 8431 | tap->wr_tsf = hdr->rxh_tsf; |
| 8432 | tap->wr_flags = IEEE80211_RADIOTAP_F_FCS0x10; |
| 8433 | tap->wr_rate = rate; |
| 8434 | tap->wr_chan_freq = |
| 8435 | htole16(ic->ic_bss->ni_chan->ic_freq)((__uint16_t)(ic->ic_bss->ni_chan->ic_freq)); |
| 8436 | tap->wr_chan_flags = |
| 8437 | htole16(ic->ic_bss->ni_chan->ic_flags)((__uint16_t)(ic->ic_bss->ni_chan->ic_flags)); |
| 8438 | tap->wr_antsignal = rssi; |
| 8439 | tap->wr_antnoise = BWI_NOISE_FLOOR-95; |
| 8440 | |
| 8441 | mb.m_datam_hdr.mh_data = (caddr_t)tap; |
| 8442 | mb.m_lenm_hdr.mh_len = sc->sc_rxtap_len; |
| 8443 | mb.m_nextm_hdr.mh_next = m; |
| 8444 | mb.m_nextpktm_hdr.mh_nextpkt = NULL((void *)0); |
| 8445 | mb.m_typem_hdr.mh_type = 0; |
| 8446 | mb.m_flagsm_hdr.mh_flags = 0; |
| 8447 | bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN(1 << 0)); |
| 8448 | } |
| 8449 | #endif |
| 8450 | |
| 8451 | m_adj(m, -IEEE80211_CRC_LEN4); |
| 8452 | |
| 8453 | wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data)); |
| 8454 | ni = ieee80211_find_rxnode(ic, wh); |
| 8455 | type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK0x0c; |
| 8456 | |
| 8457 | memset(&rxi, 0, sizeof(rxi))__builtin_memset((&rxi), (0), (sizeof(rxi))); |
| 8458 | rxi.rxi_rssi = hdr->rxh_rssi; |
| 8459 | rxi.rxi_tstamp = letoh16(hdr->rxh_tsf)((__uint16_t)(hdr->rxh_tsf)); |
| 8460 | ieee80211_inputm(ifp, m, ni, &rxi, &ml); |
| 8461 | |
| 8462 | ieee80211_release_node(ic, ni); |
| 8463 | |
| 8464 | if (type == IEEE80211_FC0_TYPE_DATA0x08) { |
| 8465 | rx_data = 1; |
| 8466 | sc->sc_rx_rate = rate; |
| 8467 | } |
| 8468 | next: |
| 8469 | idx = (idx + 1) % BWI_RX_NDESC64; |
| 8470 | } |
| 8471 | if_input(ifp, &ml); |
| 8472 | |
| 8473 | rbd->rbd_idx = idx; |
| 8474 | bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rd-> rdata_dmap), (0), (rd->rdata_dmap->dm_mapsize), (0x04)) |
| 8475 | rd->rdata_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rd-> rdata_dmap), (0), (rd->rdata_dmap->dm_mapsize), (0x04)); |
| 8476 | |
| 8477 | return (rx_data); |
| 8478 | } |
| 8479 | |
| 8480 | int |
| 8481 | bwi_rxeof32(struct bwi_softc *sc) |
| 8482 | { |
| 8483 | uint32_t val, rx_ctrl; |
| 8484 | int end_idx, rx_data; |
| 8485 | |
| 8486 | rx_ctrl = sc->sc_rx_rdata.rdata_txrx_ctrl; |
| 8487 | |
| 8488 | val = CSR_READ_4(sc, rx_ctrl + BWI_RX32_STATUS)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((rx_ctrl + 0x1c)))); |
| 8489 | end_idx = __SHIFTOUT(val, BWI_RX32_STATUS_INDEX_MASK)(((val) & (0x0fff)) / ((((0x0fff) - 1) & (0x0fff)) ^ ( 0x0fff))) / |
| 8490 | sizeof(struct bwi_desc32); |
| 8491 | |
| 8492 | rx_data = bwi_rxeof(sc, end_idx); |
| 8493 | |
| 8494 | CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_INDEX,(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((rx_ctrl + 0x18)), ((end_idx * sizeof(struct bwi_desc32))))) |
| 8495 | end_idx * sizeof(struct bwi_desc32))(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((rx_ctrl + 0x18)), ((end_idx * sizeof(struct bwi_desc32))))); |
| 8496 | |
| 8497 | return (rx_data); |
| 8498 | } |
| 8499 | |
| 8500 | void |
| 8501 | bwi_reset_rx_ring32(struct bwi_softc *sc, uint32_t rx_ctrl) |
| 8502 | { |
| 8503 | int i; |
| 8504 | |
| 8505 | CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_CTRL, 0)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((rx_ctrl + 0x10)), ((0)))); |
| 8506 | |
| 8507 | #define NRETRY 10 |
| 8508 | for (i = 0; i < NRETRY; ++i) { |
| 8509 | uint32_t status; |
| 8510 | |
| 8511 | status = CSR_READ_4(sc, rx_ctrl + BWI_RX32_STATUS)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((rx_ctrl + 0x1c)))); |
| 8512 | if (__SHIFTOUT(status, BWI_RX32_STATUS_STATE_MASK)(((status) & (0xf000)) / ((((0xf000) - 1) & (0xf000)) ^ (0xf000))) == |
| 8513 | BWI_RX32_STATUS_STATE_DISABLED0) |
| 8514 | break; |
| 8515 | |
| 8516 | DELAY(1000)(*delay_func)(1000); |
| 8517 | } |
| 8518 | if (i == NRETRY) |
| 8519 | printf("%s: reset rx ring timedout\n", sc->sc_dev.dv_xname); |
| 8520 | #undef NRETRY |
| 8521 | |
| 8522 | CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_RINGINFO, 0)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((rx_ctrl + 0x14)), ((0)))); |
| 8523 | } |
| 8524 | |
| 8525 | void |
| 8526 | bwi_free_txstats32(struct bwi_softc *sc) |
| 8527 | { |
| 8528 | bwi_reset_rx_ring32(sc, sc->sc_txstats->stats_ctrl_base); |
| 8529 | } |
| 8530 | |
| 8531 | void |
| 8532 | bwi_free_rx_ring32(struct bwi_softc *sc) |
| 8533 | { |
| 8534 | struct bwi_ring_data *rd = &sc->sc_rx_rdata; |
| 8535 | struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata; |
| 8536 | int i; |
| 8537 | |
| 8538 | bwi_reset_rx_ring32(sc, rd->rdata_txrx_ctrl); |
| 8539 | |
| 8540 | for (i = 0; i < BWI_RX_NDESC64; ++i) { |
| 8541 | struct bwi_rxbuf *rb = &rbd->rbd_buf[i]; |
| 8542 | |
| 8543 | if (rb->rb_mbuf != NULL((void *)0)) { |
| 8544 | bus_dmamap_unload(sc->sc_dmat, rb->rb_dmap)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (rb-> rb_dmap)); |
| 8545 | m_freem(rb->rb_mbuf); |
| 8546 | rb->rb_mbuf = NULL((void *)0); |
| 8547 | } |
| 8548 | } |
| 8549 | } |
| 8550 | |
| 8551 | void |
| 8552 | bwi_free_tx_ring32(struct bwi_softc *sc, int ring_idx) |
| 8553 | { |
| 8554 | struct ieee80211com *ic = &sc->sc_ic; |
| 8555 | struct bwi_ring_data *rd; |
| 8556 | struct bwi_txbuf_data *tbd; |
| 8557 | uint32_t state, val; |
| 8558 | int i; |
| 8559 | |
| 8560 | KASSERT(ring_idx < BWI_TX_NRING)((ring_idx < 6) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c" , 8560, "ring_idx < BWI_TX_NRING")); |
| 8561 | rd = &sc->sc_tx_rdata[ring_idx]; |
| 8562 | tbd = &sc->sc_tx_bdata[ring_idx]; |
| 8563 | |
| 8564 | #define NRETRY 10 |
| 8565 | for (i = 0; i < NRETRY; ++i) { |
| 8566 | val = CSR_READ_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_STATUS)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((rd-> rdata_txrx_ctrl + 0xc)))); |
| 8567 | state = __SHIFTOUT(val, BWI_TX32_STATUS_STATE_MASK)(((val) & (0xf000)) / ((((0xf000) - 1) & (0xf000)) ^ ( 0xf000))); |
| 8568 | if (state == BWI_TX32_STATUS_STATE_DISABLED0 || |
| 8569 | state == BWI_TX32_STATUS_STATE_IDLE2 || |
| 8570 | state == BWI_TX32_STATUS_STATE_STOPPED3) |
| 8571 | break; |
| 8572 | |
| 8573 | DELAY(1000)(*delay_func)(1000); |
| 8574 | } |
| 8575 | if (i == NRETRY) { |
| 8576 | printf("%s: wait for TX ring(%d) stable timed out\n", |
| 8577 | sc->sc_dev.dv_xname, ring_idx); |
| 8578 | } |
| 8579 | |
| 8580 | CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_CTRL, 0)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((rd-> rdata_txrx_ctrl + 0x0)), ((0)))); |
| 8581 | for (i = 0; i < NRETRY; ++i) { |
| 8582 | val = CSR_READ_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_STATUS)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((rd-> rdata_txrx_ctrl + 0xc)))); |
| 8583 | state = __SHIFTOUT(val, BWI_TX32_STATUS_STATE_MASK)(((val) & (0xf000)) / ((((0xf000) - 1) & (0xf000)) ^ ( 0xf000))); |
| 8584 | if (state == BWI_TX32_STATUS_STATE_DISABLED0) |
| 8585 | break; |
| 8586 | |
| 8587 | DELAY(1000)(*delay_func)(1000); |
| 8588 | } |
| 8589 | if (i == NRETRY) |
| 8590 | printf("%s: reset TX ring (%d) timed out\n", |
| 8591 | sc->sc_dev.dv_xname, ring_idx); |
| 8592 | #undef NRETRY |
| 8593 | |
| 8594 | DELAY(1000)(*delay_func)(1000); |
| 8595 | |
| 8596 | CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_RINGINFO, 0)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((rd-> rdata_txrx_ctrl + 0x4)), ((0)))); |
| 8597 | |
| 8598 | for (i = 0; i < BWI_TX_NDESC128; ++i) { |
| 8599 | struct bwi_txbuf *tb = &tbd->tbd_buf[i]; |
| 8600 | |
| 8601 | if (tb->tb_mbuf != NULL((void *)0)) { |
| 8602 | bus_dmamap_unload(sc->sc_dmat, tb->tb_dmap)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (tb-> tb_dmap)); |
| 8603 | m_freem(tb->tb_mbuf); |
| 8604 | tb->tb_mbuf = NULL((void *)0); |
| 8605 | } |
| 8606 | if (tb->tb_ni != NULL((void *)0)) { |
| 8607 | ieee80211_release_node(ic, tb->tb_ni); |
| 8608 | tb->tb_ni = NULL((void *)0); |
| 8609 | } |
| 8610 | } |
| 8611 | } |
| 8612 | |
| 8613 | uint8_t |
| 8614 | bwi_plcp2rate(uint32_t plcp0, enum ieee80211_phymode phymode) |
| 8615 | { |
| 8616 | uint32_t plcp = letoh32(plcp0)((__uint32_t)(plcp0)) & IEEE80211_OFDM_PLCP_RATE_MASK0x0000000f; |
| 8617 | return (ieee80211_plcp2rate(plcp, phymode)); |
| 8618 | } |
| 8619 | |
| 8620 | void |
| 8621 | bwi_ofdm_plcp_header(uint32_t *plcp0, int pkt_len, uint8_t rate) |
| 8622 | { |
| 8623 | uint32_t plcp; |
| 8624 | |
| 8625 | plcp = __SHIFTIN(ieee80211_rate2plcp(rate, IEEE80211_MODE_11G),((ieee80211_rate2plcp(rate, IEEE80211_MODE_11G)) * ((((0x0000000f ) - 1) & (0x0000000f)) ^ (0x0000000f))) |
| 8626 | IEEE80211_OFDM_PLCP_RATE_MASK)((ieee80211_rate2plcp(rate, IEEE80211_MODE_11G)) * ((((0x0000000f ) - 1) & (0x0000000f)) ^ (0x0000000f))) | |
| 8627 | __SHIFTIN(pkt_len, IEEE80211_OFDM_PLCP_LEN_MASK)((pkt_len) * ((((0x0001ffe0) - 1) & (0x0001ffe0)) ^ (0x0001ffe0 ))); |
| 8628 | *plcp0 = htole32(plcp)((__uint32_t)(plcp)); |
| 8629 | } |
| 8630 | |
| 8631 | void |
| 8632 | bwi_ds_plcp_header(struct ieee80211_ds_plcp_hdr *plcp, int pkt_len, |
| 8633 | uint8_t rate) |
| 8634 | { |
| 8635 | int len, service, pkt_bitlen; |
| 8636 | |
| 8637 | pkt_bitlen = pkt_len * NBBY8; |
| 8638 | len = howmany(pkt_bitlen * 2, rate)(((pkt_bitlen * 2) + ((rate) - 1)) / (rate)); |
| 8639 | |
| 8640 | service = IEEE80211_DS_PLCP_SERVICE_LOCKED0x04; |
| 8641 | if (rate == (11 * 2)) { |
| 8642 | int pkt_bitlen1; |
| 8643 | |
| 8644 | /* |
| 8645 | * PLCP service field needs to be adjusted, |
| 8646 | * if TX rate is 11Mbytes/s |
| 8647 | */ |
| 8648 | pkt_bitlen1 = len * 11; |
| 8649 | if (pkt_bitlen1 - pkt_bitlen >= NBBY8) |
| 8650 | service |= IEEE80211_DS_PLCP_SERVICE_LENEXT70x80; |
| 8651 | } |
| 8652 | |
| 8653 | plcp->i_signal = ieee80211_rate2plcp(rate, IEEE80211_MODE_11B); |
| 8654 | plcp->i_service = service; |
| 8655 | plcp->i_length = htole16(len)((__uint16_t)(len)); |
| 8656 | /* NOTE: do NOT touch i_crc */ |
| 8657 | } |
| 8658 | |
| 8659 | void |
| 8660 | bwi_plcp_header(void *plcp, int pkt_len, uint8_t rate) |
| 8661 | { |
| 8662 | enum bwi_modtype modtype; |
| 8663 | |
| 8664 | /* |
| 8665 | * Assume caller has zeroed 'plcp' |
| 8666 | */ |
| 8667 | |
| 8668 | modtype = bwi_rate2modtype(rate); |
| 8669 | if (modtype == IEEE80211_MODTYPE_OFDM) |
| 8670 | bwi_ofdm_plcp_header(plcp, pkt_len, rate); |
| 8671 | else if (modtype == IEEE80211_MODTYPE_DS) |
| 8672 | bwi_ds_plcp_header(plcp, pkt_len, rate); |
| 8673 | else |
| 8674 | panic("unsupported modulation type %u", modtype); |
| 8675 | } |
| 8676 | |
| 8677 | enum bwi_modtype |
| 8678 | bwi_rate2modtype(uint8_t rate) |
| 8679 | { |
| 8680 | rate &= IEEE80211_RATE_VAL0x7f; |
| 8681 | |
| 8682 | if (rate == 44) |
| 8683 | return IEEE80211_MODTYPE_PBCC; |
| 8684 | else if (rate == 22 || rate < 12) |
| 8685 | return IEEE80211_MODTYPE_DS; |
| 8686 | else |
| 8687 | return IEEE80211_MODTYPE_OFDM; |
| 8688 | } |
| 8689 | |
| 8690 | uint8_t |
| 8691 | bwi_ack_rate(struct ieee80211_node *ni, uint8_t rate) |
| 8692 | { |
| 8693 | const struct ieee80211_rateset *rs = &ni->ni_rates; |
| 8694 | uint8_t ack_rate = 0; |
| 8695 | enum bwi_modtype modtype; |
| 8696 | int i; |
| 8697 | |
| 8698 | rate &= IEEE80211_RATE_VAL0x7f; |
| 8699 | |
| 8700 | modtype = bwi_rate2modtype(rate); |
| 8701 | |
| 8702 | for (i = 0; i < rs->rs_nrates; ++i) { |
| 8703 | uint8_t rate1 = rs->rs_rates[i] & IEEE80211_RATE_VAL0x7f; |
| 8704 | |
| 8705 | if (rate1 > rate) { |
| 8706 | if (ack_rate != 0) |
| 8707 | return ack_rate; |
| 8708 | else |
| 8709 | break; |
| 8710 | } |
| 8711 | |
| 8712 | if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC0x80) && |
| 8713 | bwi_rate2modtype(rate1) == modtype) |
| 8714 | ack_rate = rate1; |
| 8715 | } |
| 8716 | |
| 8717 | switch (rate) { |
| 8718 | /* CCK */ |
| 8719 | case 2: |
| 8720 | case 4: |
| 8721 | case 11: |
| 8722 | case 22: |
| 8723 | ack_rate = rate; |
| 8724 | break; |
| 8725 | /* PBCC */ |
| 8726 | case 44: |
| 8727 | ack_rate = 22; |
| 8728 | break; |
| 8729 | |
| 8730 | /* OFDM */ |
| 8731 | case 12: |
| 8732 | case 18: |
| 8733 | ack_rate = 12; |
| 8734 | break; |
| 8735 | case 24: |
| 8736 | case 36: |
| 8737 | ack_rate = 24; |
| 8738 | break; |
| 8739 | case 48: |
| 8740 | case 72: |
| 8741 | case 96: |
| 8742 | case 108: |
| 8743 | ack_rate = 48; |
| 8744 | break; |
| 8745 | default: |
| 8746 | panic("unsupported rate %d", rate); |
| 8747 | } |
| 8748 | return ack_rate; |
| 8749 | } |
| 8750 | |
| 8751 | #define IEEE80211_OFDM_TXTIME(kbps, frmlen)(16 + 4 + (((((16 + ((((frmlen))) * 8) + 6)) + (((((((kbps))) * 4) / 1000)) - 1)) / ((((((kbps))) * 4) / 1000))) * 4)) \ |
| 8752 | (IEEE80211_OFDM_PREAMBLE_TIME16 + \ |
| 8753 | IEEE80211_OFDM_SIGNAL_TIME4 + \ |
| 8754 | (IEEE80211_OFDM_NSYMS((kbps), (frmlen))((((16 + ((((frmlen))) * 8) + 6)) + (((((((kbps))) * 4) / 1000 )) - 1)) / ((((((kbps))) * 4) / 1000))) * IEEE80211_OFDM_SYM_TIME4)) |
| 8755 | |
| 8756 | #define IEEE80211_OFDM_SYM_TIME4 4 |
| 8757 | #define IEEE80211_OFDM_PREAMBLE_TIME16 16 |
| 8758 | #define IEEE80211_OFDM_SIGNAL_EXT_TIME6 6 |
| 8759 | #define IEEE80211_OFDM_SIGNAL_TIME4 4 |
| 8760 | |
| 8761 | #define IEEE80211_OFDM_PLCP_SERVICE_NBITS16 16 |
| 8762 | #define IEEE80211_OFDM_TAIL_NBITS6 6 |
| 8763 | |
| 8764 | #define IEEE80211_OFDM_NBITS(frmlen)(16 + ((frmlen) * 8) + 6) \ |
| 8765 | (IEEE80211_OFDM_PLCP_SERVICE_NBITS16 + \ |
| 8766 | ((frmlen) * NBBY8) + \ |
| 8767 | IEEE80211_OFDM_TAIL_NBITS6) |
| 8768 | |
| 8769 | #define IEEE80211_OFDM_NBITS_PER_SYM(kbps)(((kbps) * 4) / 1000) \ |
| 8770 | (((kbps) * IEEE80211_OFDM_SYM_TIME4) / 1000) |
| 8771 | |
| 8772 | #define IEEE80211_OFDM_NSYMS(kbps, frmlen)((((16 + (((frmlen)) * 8) + 6)) + ((((((kbps)) * 4) / 1000)) - 1)) / (((((kbps)) * 4) / 1000))) \ |
| 8773 | howmany(IEEE80211_OFDM_NBITS((frmlen)), \((((16 + (((frmlen)) * 8) + 6)) + ((((((kbps)) * 4) / 1000)) - 1)) / (((((kbps)) * 4) / 1000))) |
| 8774 | IEEE80211_OFDM_NBITS_PER_SYM((kbps)))((((16 + (((frmlen)) * 8) + 6)) + ((((((kbps)) * 4) / 1000)) - 1)) / (((((kbps)) * 4) / 1000))) |
| 8775 | |
| 8776 | #define IEEE80211_CCK_TXTIME(kbps, frmlen)((((((frmlen)) * 8) * 1000) + (kbps) - 1) / (kbps)) \ |
| 8777 | (((IEEE80211_CCK_NBITS((frmlen))(((frmlen)) * 8) * 1000) + (kbps) - 1) / (kbps)) |
| 8778 | |
| 8779 | #define IEEE80211_CCK_PREAMBLE_LEN144 144 |
| 8780 | #define IEEE80211_CCK_PLCP_HDR_TIME48 48 |
| 8781 | #define IEEE80211_CCK_SHPREAMBLE_LEN72 72 |
| 8782 | #define IEEE80211_CCK_SHPLCP_HDR_TIME24 24 |
| 8783 | |
| 8784 | #define IEEE80211_CCK_NBITS(frmlen)((frmlen) * 8) ((frmlen) * NBBY8) |
| 8785 | |
| 8786 | uint16_t |
| 8787 | bwi_txtime(struct ieee80211com *ic, struct ieee80211_node *ni, uint len, |
| 8788 | uint8_t rs_rate, uint32_t flags) |
| 8789 | { |
| 8790 | enum bwi_modtype modtype; |
| 8791 | uint16_t txtime; |
| 8792 | int rate; |
| 8793 | |
| 8794 | rs_rate &= IEEE80211_RATE_VAL0x7f; |
| 8795 | |
| 8796 | rate = rs_rate * 500; /* ieee80211 rate -> kbps */ |
| 8797 | |
| 8798 | modtype = bwi_rate2modtype(rs_rate); |
| 8799 | if (modtype == IEEE80211_MODTYPE_OFDM) { |
| 8800 | /* |
| 8801 | * IEEE Std 802.11a-1999, page 37, equation (29) |
| 8802 | * IEEE Std 802.11g-2003, page 44, equation (42) |
| 8803 | */ |
| 8804 | txtime = IEEE80211_OFDM_TXTIME(rate, len)(16 + 4 + (((((16 + ((((len))) * 8) + 6)) + (((((((rate))) * 4 ) / 1000)) - 1)) / ((((((rate))) * 4) / 1000))) * 4)); |
| 8805 | if (ic->ic_curmode == IEEE80211_MODE_11G) |
| 8806 | txtime += IEEE80211_OFDM_SIGNAL_EXT_TIME6; |
| 8807 | } else { |
| 8808 | /* |
| 8809 | * IEEE Std 802.11b-1999, page 28, subclause 18.3.4 |
| 8810 | * IEEE Std 802.11g-2003, page 45, equation (43) |
| 8811 | */ |
| 8812 | if (modtype == IEEE80211_MODTYPE_PBCC) |
| 8813 | ++len; |
| 8814 | txtime = IEEE80211_CCK_TXTIME(rate, len)((((((len)) * 8) * 1000) + (rate) - 1) / (rate)); |
| 8815 | |
| 8816 | /* |
| 8817 | * Short preamble is not applicable for DS 1Mbits/s |
| 8818 | */ |
| 8819 | if (rs_rate != 2 && (flags & IEEE80211_F_SHPREAMBLE0x00040000)) { |
| 8820 | txtime += IEEE80211_CCK_SHPREAMBLE_LEN72 + |
| 8821 | IEEE80211_CCK_SHPLCP_HDR_TIME24; |
| 8822 | } else { |
| 8823 | txtime += IEEE80211_CCK_PREAMBLE_LEN144 + |
| 8824 | IEEE80211_CCK_PLCP_HDR_TIME48; |
| 8825 | } |
| 8826 | } |
| 8827 | return txtime; |
| 8828 | } |
| 8829 | |
| 8830 | int |
| 8831 | bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m, |
| 8832 | struct ieee80211_node *ni) |
| 8833 | { |
| 8834 | DPRINTF(2, "%s: %s\n", sc->sc_dev.dv_xname, __func__); |
| 8835 | |
| 8836 | struct ieee80211com *ic = &sc->sc_ic; |
| 8837 | struct bwi_ring_data *rd = &sc->sc_tx_rdata[BWI_TX_DATA_RING1]; |
| 8838 | struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING1]; |
| 8839 | struct bwi_txbuf *tb = &tbd->tbd_buf[idx]; |
| 8840 | struct bwi_mac *mac; |
| 8841 | struct bwi_txbuf_hdr *hdr; |
| 8842 | struct ieee80211_frame *wh; |
| 8843 | uint8_t rate; |
| 8844 | uint32_t mac_ctrl; |
| 8845 | uint16_t phy_ctrl; |
| 8846 | bus_addr_t paddr; |
| 8847 | int pkt_len, error = 0; |
| 8848 | #if 0 |
| 8849 | const uint8_t *p; |
| 8850 | int i; |
| 8851 | #endif |
| 8852 | |
| 8853 | KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC)((sc->sc_cur_regwin->rw_type == 0x812) ? (void)0 : __assert ("diagnostic ", "/usr/src/sys/dev/ic/bwi.c", 8853, "sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC" )); |
| 8854 | mac = (struct bwi_mac *)sc->sc_cur_regwin; |
| 8855 | |
| 8856 | wh = mtod(m, struct ieee80211_frame *)((struct ieee80211_frame *)((m)->m_hdr.mh_data)); |
| 8857 | |
| 8858 | /* Get 802.11 frame len before prepending TX header */ |
| 8859 | pkt_len = m->m_pkthdrM_dat.MH.MH_pkthdr.len + IEEE80211_CRC_LEN4; |
| 8860 | |
| 8861 | /* |
| 8862 | * Find TX rate |
| 8863 | */ |
| 8864 | bzero(tb->tb_rate_idx, sizeof(tb->tb_rate_idx))__builtin_bzero((tb->tb_rate_idx), (sizeof(tb->tb_rate_idx ))); |
| 8865 | if (ni != NULL((void *)0)) { |
| 8866 | if (ic->ic_fixed_rate != -1) { |
| 8867 | rate = ic->ic_sup_rates[ic->ic_curmode]. |
| 8868 | rs_rates[ic->ic_fixed_rate]; |
| 8869 | } else { |
| 8870 | /* AMRR rate control */ |
| 8871 | rate = ni->ni_rates.rs_rates[ni->ni_txrate]; |
| 8872 | } |
| 8873 | } else { |
| 8874 | /* Fixed at 1Mbytes/s for mgt frames */ |
| 8875 | rate = (1 * 2); |
| 8876 | } |
| 8877 | |
| 8878 | rate &= IEEE80211_RATE_VAL0x7f; |
| 8879 | |
| 8880 | if (IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01)) |
| 8881 | rate = (1 * 2); |
| 8882 | |
| 8883 | if (rate == 0) { |
| 8884 | printf("%s: invalid rate %u or fallback rate", |
| 8885 | sc->sc_dev.dv_xname, rate); |
| 8886 | rate = (1 * 2); /* Force 1Mbytes/s */ |
| 8887 | } |
| 8888 | sc->sc_tx_rate = rate; |
| 8889 | |
| 8890 | #if NBPFILTER1 > 0 |
| 8891 | /* TX radio tap */ |
| 8892 | if (sc->sc_drvbpf != NULL((void *)0)) { |
| 8893 | struct mbuf mb; |
| 8894 | struct bwi_tx_radiotap_hdr *tap = &sc->sc_txtapsc_txtapu.th; |
| 8895 | |
| 8896 | tap->wt_flags = 0; |
| 8897 | tap->wt_rate = rate; |
| 8898 | tap->wt_chan_freq = |
| 8899 | htole16(ic->ic_bss->ni_chan->ic_freq)((__uint16_t)(ic->ic_bss->ni_chan->ic_freq)); |
| 8900 | tap->wt_chan_flags = |
| 8901 | htole16(ic->ic_bss->ni_chan->ic_flags)((__uint16_t)(ic->ic_bss->ni_chan->ic_flags)); |
| 8902 | |
| 8903 | mb.m_datam_hdr.mh_data = (caddr_t)tap; |
| 8904 | mb.m_lenm_hdr.mh_len = sc->sc_txtap_len; |
| 8905 | mb.m_nextm_hdr.mh_next = m; |
| 8906 | mb.m_nextpktm_hdr.mh_nextpkt = NULL((void *)0); |
| 8907 | mb.m_typem_hdr.mh_type = 0; |
| 8908 | mb.m_flagsm_hdr.mh_flags = 0; |
| 8909 | bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT(1 << 1)); |
| 8910 | } |
| 8911 | #endif |
| 8912 | |
| 8913 | /* |
| 8914 | * Setup the embedded TX header |
| 8915 | */ |
| 8916 | M_PREPEND(m, sizeof(*hdr), M_DONTWAIT)(m) = m_prepend((m), (sizeof(*hdr)), (0x0002)); |
| 8917 | if (m == NULL((void *)0)) { |
| 8918 | printf("%s: prepend TX header failed\n", sc->sc_dev.dv_xname); |
| 8919 | return (ENOBUFS55); |
| 8920 | } |
| 8921 | hdr = mtod(m, struct bwi_txbuf_hdr *)((struct bwi_txbuf_hdr *)((m)->m_hdr.mh_data)); |
| 8922 | |
| 8923 | bzero(hdr, sizeof(*hdr))__builtin_bzero((hdr), (sizeof(*hdr))); |
| 8924 | |
| 8925 | bcopy(wh->i_fc, hdr->txh_fc, sizeof(hdr->txh_fc)); |
| 8926 | bcopy(wh->i_addr1, hdr->txh_addr1, sizeof(hdr->txh_addr1)); |
| 8927 | |
| 8928 | if (ni != NULL((void *)0) && !IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01)) { |
| 8929 | uint16_t dur; |
| 8930 | uint8_t ack_rate; |
| 8931 | |
| 8932 | ack_rate = bwi_ack_rate(ni, rate); |
| 8933 | dur = bwi_txtime(ic, ni, |
| 8934 | sizeof(struct ieee80211_frame_ack) + IEEE80211_CRC_LEN4, |
| 8935 | ack_rate, ic->ic_flags & IEEE80211_F_SHPREAMBLE0x00040000); |
| 8936 | |
| 8937 | hdr->txh_fb_duration = htole16(dur)((__uint16_t)(dur)); |
| 8938 | } |
| 8939 | |
| 8940 | hdr->txh_id = __SHIFTIN(BWI_TX_DATA_RING, BWI_TXH_ID_RING_MASK)((1) * ((((0xe000) - 1) & (0xe000)) ^ (0xe000))) | |
| 8941 | __SHIFTIN(idx, BWI_TXH_ID_IDX_MASK)((idx) * ((((0x1fff) - 1) & (0x1fff)) ^ (0x1fff))); |
| 8942 | |
| 8943 | bwi_plcp_header(hdr->txh_plcp, pkt_len, rate); |
| 8944 | bwi_plcp_header(hdr->txh_fb_plcp, pkt_len, rate); |
| 8945 | |
| 8946 | phy_ctrl = __SHIFTIN(mac->mac_rf.rf_ant_mode,((mac->mac_rf.rf_ant_mode) * ((((0x0300) - 1) & (0x0300 )) ^ (0x0300))) |
| 8947 | BWI_TXH_PHY_C_ANTMODE_MASK)((mac->mac_rf.rf_ant_mode) * ((((0x0300) - 1) & (0x0300 )) ^ (0x0300))); |
| 8948 | if (bwi_rate2modtype(rate) == IEEE80211_MODTYPE_OFDM) |
| 8949 | phy_ctrl |= BWI_TXH_PHY_C_OFDM(1 << 0); |
| 8950 | else if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE0x00040000) && rate != (2 * 1)) |
| 8951 | phy_ctrl |= BWI_TXH_PHY_C_SHPREAMBLE(1 << 4); |
| 8952 | |
| 8953 | mac_ctrl = BWI_TXH_MAC_C_HWSEQ(1 << 4) | BWI_TXH_MAC_C_FIRST_FRAG(1 << 3); |
| 8954 | if (!IEEE80211_IS_MULTICAST(wh->i_addr1)(*(wh->i_addr1) & 0x01)) |
| 8955 | mac_ctrl |= BWI_TXH_MAC_C_ACK(1 << 0); |
| 8956 | if (bwi_rate2modtype(rate) == IEEE80211_MODTYPE_OFDM) |
| 8957 | mac_ctrl |= BWI_TXH_MAC_C_FB_OFDM(1 << 8); |
| 8958 | |
| 8959 | hdr->txh_mac_ctrl = htole32(mac_ctrl)((__uint32_t)(mac_ctrl)); |
| 8960 | hdr->txh_phy_ctrl = htole16(phy_ctrl)((__uint16_t)(phy_ctrl)); |
| 8961 | |
| 8962 | /* Catch any further usage */ |
| 8963 | hdr = NULL((void *)0); |
| 8964 | wh = NULL((void *)0); |
| 8965 | |
| 8966 | if (sc->sc_bus_space == BWI_BUS_SPACE_30BIT) { |
| 8967 | /* Bounce for 30bit devices. */ |
| 8968 | m_copydata(m, 0, m->m_pkthdrM_dat.MH.MH_pkthdr.len, |
| 8969 | sc->sc_bounce_tx_data[BWI_TX_DATA_RING1] + |
| 8970 | (MCLBYTES(1 << 11) * idx)); |
| 8971 | } else { |
| 8972 | /* DMA load */ |
| 8973 | error = bus_dmamap_load_mbuf(sc->sc_dmat, tb->tb_dmap, m,(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), ( tb->tb_dmap), (m), (0x0001)) |
| 8974 | BUS_DMA_NOWAIT)(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), ( tb->tb_dmap), (m), (0x0001)); |
| 8975 | if (error && error != EFBIG27) { |
| 8976 | printf("%s: can't load TX buffer (1) %d\n", |
| 8977 | sc->sc_dev.dv_xname, error); |
| 8978 | goto back; |
| 8979 | } |
| 8980 | |
| 8981 | if (error) { /* error == EFBIG */ |
| 8982 | if (m_defrag(m, M_DONTWAIT0x0002)) { |
| 8983 | printf("%s: can't defrag TX buffer\n", |
| 8984 | sc->sc_dev.dv_xname); |
| 8985 | goto back; |
| 8986 | } |
| 8987 | error = bus_dmamap_load_mbuf(sc->sc_dmat, tb->tb_dmap,(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), ( tb->tb_dmap), (m), (0x0001)) |
| 8988 | m, BUS_DMA_NOWAIT)(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), ( tb->tb_dmap), (m), (0x0001)); |
| 8989 | if (error) { |
| 8990 | printf("%s: can't load TX buffer (2) %d\n", |
| 8991 | sc->sc_dev.dv_xname, error); |
| 8992 | goto back; |
| 8993 | } |
| 8994 | } |
| 8995 | error = 0; |
| 8996 | } |
| 8997 | |
| 8998 | bus_dmamap_sync(sc->sc_dmat, tb->tb_dmap, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (tb-> tb_dmap), (0), (tb->tb_dmap->dm_mapsize), (0x04)) |
| 8999 | tb->tb_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (tb-> tb_dmap), (0), (tb->tb_dmap->dm_mapsize), (0x04)); |
| 9000 | |
| 9001 | tb->tb_mbuf = m; |
| 9002 | tb->tb_ni = ni; |
| 9003 | |
| 9004 | #if 0 |
| 9005 | p = mtod(m, const uint8_t *)((const uint8_t *)((m)->m_hdr.mh_data)); |
| 9006 | for (i = 0; i < m->m_pkthdrM_dat.MH.MH_pkthdr.len; ++i) { |
| 9007 | if (i != 0 && i % 8 == 0) |
| 9008 | printf("\n"); |
| 9009 | printf("%02x ", p[i]); |
| 9010 | } |
| 9011 | printf("\n"); |
| 9012 | |
| 9013 | DPRINTF(1, "%s: idx %d, pkt_len %d, buflen %d\n", |
| 9014 | sc->sc_dev.dv_xname, idx, pkt_len, m->m_pkthdr.len); |
| 9015 | #endif |
| 9016 | |
| 9017 | /* Setup TX descriptor */ |
| 9018 | paddr = tb->tb_dmap->dm_segs[0].ds_addr; |
| 9019 | sc->sc_setup_txdesc(sc, rd, idx, paddr, m->m_pkthdrM_dat.MH.MH_pkthdr.len); |
| 9020 | bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rd-> rdata_dmap), (0), (rd->rdata_dmap->dm_mapsize), (0x04)) |
| 9021 | rd->rdata_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (rd-> rdata_dmap), (0), (rd->rdata_dmap->dm_mapsize), (0x04)); |
| 9022 | |
| 9023 | /* Kick start */ |
| 9024 | sc->sc_start_tx(sc, rd->rdata_txrx_ctrl, idx); |
| 9025 | |
| 9026 | back: |
| 9027 | if (error) |
| 9028 | m_freem(m); |
| 9029 | return (error); |
| 9030 | } |
| 9031 | |
| 9032 | void |
| 9033 | bwi_start_tx32(struct bwi_softc *sc, uint32_t tx_ctrl, int idx) |
| 9034 | { |
| 9035 | idx = (idx + 1) % BWI_TX_NDESC128; |
| 9036 | CSR_WRITE_4(sc, tx_ctrl + BWI_TX32_INDEX,(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((tx_ctrl + 0x8)), ((idx * sizeof(struct bwi_desc32))))) |
| 9037 | idx * sizeof(struct bwi_desc32))(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((tx_ctrl + 0x8)), ((idx * sizeof(struct bwi_desc32))))); |
| 9038 | } |
| 9039 | |
| 9040 | void |
| 9041 | bwi_txeof_status32(struct bwi_softc *sc) |
| 9042 | { |
| 9043 | struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if; |
| 9044 | uint32_t val, ctrl_base; |
| 9045 | int end_idx; |
| 9046 | |
| 9047 | ctrl_base = sc->sc_txstats->stats_ctrl_base; |
| 9048 | |
| 9049 | val = CSR_READ_4(sc, ctrl_base + BWI_RX32_STATUS)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((ctrl_base + 0x1c)))); |
| 9050 | end_idx = __SHIFTOUT(val, BWI_RX32_STATUS_INDEX_MASK)(((val) & (0x0fff)) / ((((0x0fff) - 1) & (0x0fff)) ^ ( 0x0fff))) / |
| 9051 | sizeof(struct bwi_desc32); |
| 9052 | |
| 9053 | bwi_txeof_status(sc, end_idx); |
| 9054 | |
| 9055 | CSR_WRITE_4(sc, ctrl_base + BWI_RX32_INDEX,(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((ctrl_base + 0x18)), ((end_idx * sizeof(struct bwi_desc32))))) |
| 9056 | end_idx * sizeof(struct bwi_desc32))(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((ctrl_base + 0x18)), ((end_idx * sizeof(struct bwi_desc32))))); |
| 9057 | |
| 9058 | if (ifq_is_oactive(&ifp->if_snd) == 0) |
| 9059 | ifp->if_start(ifp); |
| 9060 | } |
| 9061 | |
| 9062 | void |
| 9063 | _bwi_txeof(struct bwi_softc *sc, uint16_t tx_id) |
| 9064 | { |
| 9065 | struct ieee80211com *ic = &sc->sc_ic; |
| 9066 | struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if; |
| 9067 | struct bwi_txbuf_data *tbd; |
| 9068 | struct bwi_txbuf *tb; |
| 9069 | int ring_idx, buf_idx; |
| 9070 | |
| 9071 | if (tx_id == 0) { |
| 9072 | printf("%s: zero tx id\n", sc->sc_dev.dv_xname); |
| 9073 | return; |
| 9074 | } |
| 9075 | |
| 9076 | ring_idx = __SHIFTOUT(tx_id, BWI_TXH_ID_RING_MASK)(((tx_id) & (0xe000)) / ((((0xe000) - 1) & (0xe000)) ^ (0xe000))); |
| 9077 | buf_idx = __SHIFTOUT(tx_id, BWI_TXH_ID_IDX_MASK)(((tx_id) & (0x1fff)) / ((((0x1fff) - 1) & (0x1fff)) ^ (0x1fff))); |
| 9078 | |
| 9079 | KASSERT(ring_idx == BWI_TX_DATA_RING)((ring_idx == 1) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c" , 9079, "ring_idx == BWI_TX_DATA_RING")); |
| 9080 | KASSERT(buf_idx < BWI_TX_NDESC)((buf_idx < 128) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/bwi.c" , 9080, "buf_idx < BWI_TX_NDESC")); |
| 9081 | #if 0 |
| 9082 | DPRINTF(1, "%s: txeof idx %d\n", sc->sc_dev.dv_xname, buf_idx); |
| 9083 | #endif |
| 9084 | tbd = &sc->sc_tx_bdata[ring_idx]; |
| 9085 | KASSERT(tbd->tbd_used > 0)((tbd->tbd_used > 0) ? (void)0 : __assert("diagnostic " , "/usr/src/sys/dev/ic/bwi.c", 9085, "tbd->tbd_used > 0" )); |
| 9086 | tbd->tbd_used--; |
| 9087 | |
| 9088 | tb = &tbd->tbd_buf[buf_idx]; |
| 9089 | |
| 9090 | bus_dmamap_unload(sc->sc_dmat, tb->tb_dmap)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (tb-> tb_dmap)); |
| 9091 | m_freem(tb->tb_mbuf); |
| 9092 | tb->tb_mbuf = NULL((void *)0); |
| 9093 | |
| 9094 | if (tb->tb_ni != NULL((void *)0)) { |
| 9095 | ieee80211_release_node(ic, tb->tb_ni); |
| 9096 | tb->tb_ni = NULL((void *)0); |
| 9097 | } |
| 9098 | |
| 9099 | if (tbd->tbd_used == 0) |
| 9100 | sc->sc_tx_timer = 0; |
| 9101 | |
| 9102 | ifq_clr_oactive(&ifp->if_snd); |
| 9103 | } |
| 9104 | |
| 9105 | void |
| 9106 | bwi_txeof_status(struct bwi_softc *sc, int end_idx) |
| 9107 | { |
| 9108 | struct bwi_txstats_data *st = sc->sc_txstats; |
| 9109 | int idx; |
| 9110 | |
| 9111 | bus_dmamap_sync(sc->sc_dmat, st->stats_dmap, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (st-> stats_dmap), (0), (st->stats_dmap->dm_mapsize), (0x02)) |
| 9112 | st->stats_dmap->dm_mapsize, BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (st-> stats_dmap), (0), (st->stats_dmap->dm_mapsize), (0x02)); |
| 9113 | |
| 9114 | idx = st->stats_idx; |
| 9115 | while (idx != end_idx) { |
| 9116 | _bwi_txeof(sc, letoh16(st->stats[idx].txs_id)((__uint16_t)(st->stats[idx].txs_id))); |
| 9117 | idx = (idx + 1) % BWI_TXSTATS_NDESC64; |
| 9118 | } |
| 9119 | st->stats_idx = idx; |
| 9120 | } |
| 9121 | |
| 9122 | void |
| 9123 | bwi_txeof(struct bwi_softc *sc) |
| 9124 | { |
| 9125 | struct ifnet *ifp = &sc->sc_ic.ic_ific_ac.ac_if; |
| 9126 | |
| 9127 | for (;;) { |
| 9128 | uint32_t tx_status0, tx_status1; |
| 9129 | uint16_t tx_id, tx_info; |
| 9130 | |
| 9131 | tx_status0 = CSR_READ_4(sc, BWI_TXSTATUS_0)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000170 )))); |
| 9132 | if (tx_status0 == 0) |
| 9133 | break; |
| 9134 | tx_status1 = CSR_READ_4(sc, BWI_TXSTATUS_1)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000174 )))); |
| 9135 | |
| 9136 | tx_id = __SHIFTOUT(tx_status0, BWI_TXSTATUS_0_TXID_MASK)(((tx_status0) & (0xffff0000)) / ((((0xffff0000) - 1) & (0xffff0000)) ^ (0xffff0000))); |
| 9137 | tx_info = BWI_TXSTATUS_0_INFO(tx_status0)(((tx_status0) & 0xfff0) | (((tx_status0) & 0xf) >> 1)); |
| 9138 | |
| 9139 | if (tx_info & 0x30) /* XXX */ |
| 9140 | continue; |
| 9141 | |
| 9142 | _bwi_txeof(sc, letoh16(tx_id)((__uint16_t)(tx_id))); |
| 9143 | } |
| 9144 | |
| 9145 | if (ifq_is_oactive(&ifp->if_snd) == 0) |
| 9146 | ifp->if_start(ifp); |
| 9147 | } |
| 9148 | |
| 9149 | int |
| 9150 | bwi_bbp_power_on(struct bwi_softc *sc, enum bwi_clock_mode clk_mode) |
| 9151 | { |
| 9152 | bwi_power_on(sc, 1); |
| 9153 | |
| 9154 | return (bwi_set_clock_mode(sc, clk_mode)); |
| 9155 | } |
| 9156 | |
| 9157 | void |
| 9158 | bwi_bbp_power_off(struct bwi_softc *sc) |
| 9159 | { |
| 9160 | bwi_set_clock_mode(sc, BWI_CLOCK_MODE_SLOW); |
| 9161 | bwi_power_off(sc, 1); |
| 9162 | } |
| 9163 | |
| 9164 | int |
| 9165 | bwi_get_pwron_delay(struct bwi_softc *sc) |
| 9166 | { |
| 9167 | struct bwi_regwin *com, *old; |
| 9168 | struct bwi_clock_freq freq; |
| 9169 | uint32_t val; |
| 9170 | int error; |
| 9171 | |
| 9172 | com = &sc->sc_com_regwin; |
| 9173 | KASSERT(BWI_REGWIN_EXIST(com))((((com)->rw_flags & 0x1)) ? (void)0 : __assert("diagnostic " , "/usr/src/sys/dev/ic/bwi.c", 9173, "BWI_REGWIN_EXIST(com)") ); |
| 9174 | |
| 9175 | if ((sc->sc_cap & BWI_CAP_CLKMODE(1 << 18)) == 0) |
| 9176 | return (0); |
| 9177 | |
| 9178 | error = bwi_regwin_switch(sc, com, &old); |
| 9179 | if (error) |
| 9180 | return (error); |
| 9181 | |
| 9182 | bwi_get_clock_freq(sc, &freq); |
| 9183 | |
| 9184 | val = CSR_READ_4(sc, BWI_PLL_ON_DELAY)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0xb0 )))); |
| 9185 | sc->sc_pwron_delay = howmany((val + 2) * 1000000, freq.clkfreq_min)((((val + 2) * 1000000) + ((freq.clkfreq_min) - 1)) / (freq.clkfreq_min )); |
| 9186 | DPRINTF(1, "%s: power on delay %u\n", |
| 9187 | sc->sc_dev.dv_xname, sc->sc_pwron_delay); |
| 9188 | |
| 9189 | return (bwi_regwin_switch(sc, old, NULL((void *)0))); |
| 9190 | } |
| 9191 | |
| 9192 | int |
| 9193 | bwi_bus_attach(struct bwi_softc *sc) |
| 9194 | { |
| 9195 | struct bwi_regwin *bus, *old; |
| 9196 | int error; |
| 9197 | |
| 9198 | bus = &sc->sc_bus_regwin; |
| 9199 | |
| 9200 | error = bwi_regwin_switch(sc, bus, &old); |
| 9201 | if (error) |
| 9202 | return (error); |
| 9203 | |
| 9204 | if (!bwi_regwin_is_enabled(sc, bus)) |
| 9205 | bwi_regwin_enable(sc, bus, 0); |
| 9206 | |
| 9207 | /* Disable interrupts */ |
| 9208 | CSR_WRITE_4(sc, BWI_INTRVEC, 0)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000f94 )), ((0)))); |
| 9209 | |
| 9210 | return (bwi_regwin_switch(sc, old, NULL((void *)0))); |
| 9211 | } |
| 9212 | |
| 9213 | const char * |
| 9214 | bwi_regwin_name(const struct bwi_regwin *rw) |
| 9215 | { |
| 9216 | switch (rw->rw_type) { |
| 9217 | case BWI_REGWIN_T_COM0x800: |
| 9218 | return ("COM"); |
| 9219 | case BWI_REGWIN_T_BUSPCI0x804: |
| 9220 | return ("PCI"); |
| 9221 | case BWI_REGWIN_T_MAC0x812: |
| 9222 | return ("MAC"); |
| 9223 | case BWI_REGWIN_T_BUSPCIE0x820: |
| 9224 | return ("PCIE"); |
| 9225 | } |
| 9226 | panic("unknown regwin type 0x%04x", rw->rw_type); |
| 9227 | |
| 9228 | return (NULL((void *)0)); |
| 9229 | } |
| 9230 | |
| 9231 | uint32_t |
| 9232 | bwi_regwin_disable_bits(struct bwi_softc *sc) |
| 9233 | { |
| 9234 | uint32_t busrev; |
| 9235 | |
| 9236 | /* XXX cache this */ |
| 9237 | busrev = __SHIFTOUT(CSR_READ_4(sc, BWI_ID_LO), BWI_ID_LO_BUSREV_MASK)((((((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000ff8 ))))) & (0xf0000000)) / ((((0xf0000000) - 1) & (0xf0000000 )) ^ (0xf0000000))); |
| 9238 | DPRINTF(1, "%s: bus rev %u\n", sc->sc_dev.dv_xname, busrev); |
| 9239 | |
| 9240 | if (busrev == BWI_BUSREV_00) |
| 9241 | return (BWI_STATE_LO_DISABLE1(1 << 1)); |
| 9242 | else if (busrev == BWI_BUSREV_11) |
| 9243 | return (BWI_STATE_LO_DISABLE2(1 << 2)); |
| 9244 | else |
| 9245 | return ((BWI_STATE_LO_DISABLE1(1 << 1) | BWI_STATE_LO_DISABLE2(1 << 2))); |
| 9246 | } |
| 9247 | |
| 9248 | int |
| 9249 | bwi_regwin_is_enabled(struct bwi_softc *sc, struct bwi_regwin *rw) |
| 9250 | { |
| 9251 | uint32_t val, disable_bits; |
| 9252 | |
| 9253 | disable_bits = bwi_regwin_disable_bits(sc); |
| 9254 | val = CSR_READ_4(sc, BWI_STATE_LO)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000f98 )))); |
| 9255 | |
| 9256 | if ((val & (BWI_STATE_LO_CLOCK(1 << 16) | |
| 9257 | BWI_STATE_LO_RESET(1 << 0) | |
| 9258 | disable_bits)) == BWI_STATE_LO_CLOCK(1 << 16)) { |
| 9259 | DPRINTF(1, "%s: %s is enabled\n", |
| 9260 | sc->sc_dev.dv_xname, bwi_regwin_name(rw)); |
| 9261 | return (1); |
| 9262 | } else { |
| 9263 | DPRINTF(1, "%s: %s is disabled\n", |
| 9264 | sc->sc_dev.dv_xname, bwi_regwin_name(rw)); |
| 9265 | return (0); |
| 9266 | } |
| 9267 | } |
| 9268 | |
| 9269 | void |
| 9270 | bwi_regwin_disable(struct bwi_softc *sc, struct bwi_regwin *rw, uint32_t flags) |
| 9271 | { |
| 9272 | uint32_t state_lo, disable_bits; |
| 9273 | int i; |
| 9274 | |
| 9275 | state_lo = CSR_READ_4(sc, BWI_STATE_LO)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000f98 )))); |
| 9276 | |
| 9277 | /* |
| 9278 | * If current regwin is in 'reset' state, it was already disabled. |
| 9279 | */ |
| 9280 | if (state_lo & BWI_STATE_LO_RESET(1 << 0)) { |
| 9281 | DPRINTF(1, "%s: %s was already disabled\n", |
| 9282 | sc->sc_dev.dv_xname, bwi_regwin_name(rw)); |
| 9283 | return; |
| 9284 | } |
| 9285 | |
| 9286 | disable_bits = bwi_regwin_disable_bits(sc); |
| 9287 | |
| 9288 | /* |
| 9289 | * Disable normal clock |
| 9290 | */ |
| 9291 | state_lo = BWI_STATE_LO_CLOCK(1 << 16) | disable_bits; |
| 9292 | CSR_WRITE_4(sc, BWI_STATE_LO, state_lo)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000f98 )), ((state_lo)))); |
| 9293 | |
| 9294 | /* |
| 9295 | * Wait until normal clock is disabled |
| 9296 | */ |
| 9297 | #define NRETRY 1000 |
| 9298 | for (i = 0; i < NRETRY; ++i) { |
| 9299 | state_lo = CSR_READ_4(sc, BWI_STATE_LO)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000f98 )))); |
| 9300 | if (state_lo & disable_bits) |
| 9301 | break; |
| 9302 | DELAY(10)(*delay_func)(10); |
| 9303 | } |
| 9304 | if (i == NRETRY) { |
| 9305 | printf("%s: %s disable clock timeout\n", |
| 9306 | sc->sc_dev.dv_xname, bwi_regwin_name(rw)); |
| 9307 | } |
| 9308 | |
| 9309 | for (i = 0; i < NRETRY; ++i) { |
| 9310 | uint32_t state_hi; |
| 9311 | |
| 9312 | state_hi = CSR_READ_4(sc, BWI_STATE_HI)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000f9c )))); |
| 9313 | if ((state_hi & BWI_STATE_HI_BUSY(1 << 2)) == 0) |
| 9314 | break; |
| 9315 | DELAY(10)(*delay_func)(10); |
| 9316 | } |
| 9317 | if (i == NRETRY) { |
| 9318 | printf("%s: %s wait BUSY unset timeout\n", |
| 9319 | sc->sc_dev.dv_xname, bwi_regwin_name(rw)); |
| 9320 | } |
| 9321 | #undef NRETRY |
| 9322 | |
| 9323 | /* |
| 9324 | * Reset and disable regwin with gated clock |
| 9325 | */ |
| 9326 | state_lo = BWI_STATE_LO_RESET(1 << 0) | disable_bits | |
| 9327 | BWI_STATE_LO_CLOCK(1 << 16) | BWI_STATE_LO_GATED_CLOCK(1 << 17) | |
| 9328 | __SHIFTIN(flags, BWI_STATE_LO_FLAGS_MASK)((flags) * ((((0x3ffc0000) - 1) & (0x3ffc0000)) ^ (0x3ffc0000 ))); |
| 9329 | CSR_WRITE_4(sc, BWI_STATE_LO, state_lo)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000f98 )), ((state_lo)))); |
| 9330 | |
| 9331 | /* Flush pending bus write */ |
| 9332 | CSR_READ_4(sc, BWI_STATE_LO)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000f98 )))); |
| 9333 | DELAY(1)(*delay_func)(1); |
| 9334 | |
| 9335 | /* Reset and disable regwin */ |
| 9336 | state_lo = BWI_STATE_LO_RESET(1 << 0) | disable_bits | |
| 9337 | __SHIFTIN(flags, BWI_STATE_LO_FLAGS_MASK)((flags) * ((((0x3ffc0000) - 1) & (0x3ffc0000)) ^ (0x3ffc0000 ))); |
| 9338 | CSR_WRITE_4(sc, BWI_STATE_LO, state_lo)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000f98 )), ((state_lo)))); |
| 9339 | |
| 9340 | /* Flush pending bus write */ |
| 9341 | CSR_READ_4(sc, BWI_STATE_LO)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000f98 )))); |
| 9342 | DELAY(1)(*delay_func)(1); |
| 9343 | } |
| 9344 | |
| 9345 | void |
| 9346 | bwi_regwin_enable(struct bwi_softc *sc, struct bwi_regwin *rw, uint32_t flags) |
| 9347 | { |
| 9348 | uint32_t state_lo, state_hi, imstate; |
| 9349 | |
| 9350 | bwi_regwin_disable(sc, rw, flags); |
| 9351 | |
| 9352 | /* Reset regwin with gated clock */ |
| 9353 | state_lo = BWI_STATE_LO_RESET(1 << 0) | |
| 9354 | BWI_STATE_LO_CLOCK(1 << 16) | |
| 9355 | BWI_STATE_LO_GATED_CLOCK(1 << 17) | |
| 9356 | __SHIFTIN(flags, BWI_STATE_LO_FLAGS_MASK)((flags) * ((((0x3ffc0000) - 1) & (0x3ffc0000)) ^ (0x3ffc0000 ))); |
| 9357 | CSR_WRITE_4(sc, BWI_STATE_LO, state_lo)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000f98 )), ((state_lo)))); |
| 9358 | |
| 9359 | /* Flush pending bus write */ |
| 9360 | CSR_READ_4(sc, BWI_STATE_LO)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000f98 )))); |
| 9361 | DELAY(1)(*delay_func)(1); |
| 9362 | |
| 9363 | state_hi = CSR_READ_4(sc, BWI_STATE_HI)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000f9c )))); |
| 9364 | if (state_hi & BWI_STATE_HI_SERROR(1 << 0)) |
| 9365 | CSR_WRITE_4(sc, BWI_STATE_HI, 0)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000f9c )), ((0)))); |
| 9366 | |
| 9367 | imstate = CSR_READ_4(sc, BWI_IMSTATE)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000f90 )))); |
| 9368 | if (imstate & (BWI_IMSTATE_INBAND_ERR(1 << 17) | BWI_IMSTATE_TIMEOUT(1 << 18))) { |
| 9369 | imstate &= ~(BWI_IMSTATE_INBAND_ERR(1 << 17) | BWI_IMSTATE_TIMEOUT(1 << 18)); |
| 9370 | CSR_WRITE_4(sc, BWI_IMSTATE, imstate)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000f90 )), ((imstate)))); |
| 9371 | } |
| 9372 | |
| 9373 | /* Enable regwin with gated clock */ |
| 9374 | state_lo = BWI_STATE_LO_CLOCK(1 << 16) | |
| 9375 | BWI_STATE_LO_GATED_CLOCK(1 << 17) | |
| 9376 | __SHIFTIN(flags, BWI_STATE_LO_FLAGS_MASK)((flags) * ((((0x3ffc0000) - 1) & (0x3ffc0000)) ^ (0x3ffc0000 ))); |
| 9377 | CSR_WRITE_4(sc, BWI_STATE_LO, state_lo)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000f98 )), ((state_lo)))); |
| 9378 | |
| 9379 | /* Flush pending bus write */ |
| 9380 | CSR_READ_4(sc, BWI_STATE_LO)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000f98 )))); |
| 9381 | DELAY(1)(*delay_func)(1); |
| 9382 | |
| 9383 | /* Enable regwin with normal clock */ |
| 9384 | state_lo = BWI_STATE_LO_CLOCK(1 << 16) | |
| 9385 | __SHIFTIN(flags, BWI_STATE_LO_FLAGS_MASK)((flags) * ((((0x3ffc0000) - 1) & (0x3ffc0000)) ^ (0x3ffc0000 ))); |
| 9386 | CSR_WRITE_4(sc, BWI_STATE_LO, state_lo)(((sc)->sc_mem_bt)->write_4(((sc)->sc_mem_bh), ((0x00000f98 )), ((state_lo)))); |
| 9387 | |
| 9388 | /* Flush pending bus write */ |
| 9389 | CSR_READ_4(sc, BWI_STATE_LO)(((sc)->sc_mem_bt)->read_4(((sc)->sc_mem_bh), ((0x00000f98 )))); |
| 9390 | DELAY(1)(*delay_func)(1); |
| 9391 | } |
| 9392 | |
| 9393 | void |
| 9394 | bwi_set_bssid(struct bwi_softc *sc, const uint8_t *bssid) |
| 9395 | { |
| 9396 | struct ieee80211com *ic = &sc->sc_ic; |
| 9397 | struct bwi_mac *mac; |
| 9398 | struct bwi_myaddr_bssid buf; |
| 9399 | const uint8_t *p; |
| 9400 | uint32_t val; |
| 9401 | int n, i; |
| 9402 | |
| 9403 | KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC)((sc->sc_cur_regwin->rw_type == 0x812) ? (void)0 : __assert ("diagnostic ", "/usr/src/sys/dev/ic/bwi.c", 9403, "sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC" )); |
| 9404 | mac = (struct bwi_mac *)sc->sc_cur_regwin; |
| 9405 | |
| 9406 | bwi_set_addr_filter(sc, BWI_ADDR_FILTER_BSSID3, bssid); |
| 9407 | |
| 9408 | bcopy(ic->ic_myaddr, buf.myaddr, sizeof(buf.myaddr)); |
| 9409 | bcopy(bssid, buf.bssid, sizeof(buf.bssid)); |
| 9410 | |
| 9411 | n = sizeof(buf) / sizeof(val); |
| 9412 | p = (const uint8_t *)&buf; |
| 9413 | for (i = 0; i < n; ++i) { |
| 9414 | int j; |
| 9415 | |
| 9416 | val = 0; |
| 9417 | for (j = 0; j < sizeof(val); ++j) |
| 9418 | val |= ((uint32_t)(*p++)) << (j * 8); |
| 9419 | |
| 9420 | TMPLT_WRITE_4(mac, 0x20 + (i * sizeof(val)), val)bwi_tmplt_write_4((mac), (0x20 + (i * sizeof(val))), (val)); |
| 9421 | } |
| 9422 | } |
| 9423 | |
| 9424 | void |
| 9425 | bwi_updateslot(struct ieee80211com *ic) |
| 9426 | { |
| 9427 | struct bwi_softc *sc = ic->ic_ific_ac.ac_if.if_softc; |
| 9428 | struct bwi_mac *mac; |
| 9429 | struct ifnet *ifp = &ic->ic_ific_ac.ac_if; |
| 9430 | |
| 9431 | if ((ifp->if_flags & IFF_RUNNING0x40) == 0) |
| 9432 | return; |
| 9433 | |
| 9434 | DPRINTF(2, "%s: %s\n", sc->sc_dev.dv_xname, __func__); |
| 9435 | |
| 9436 | KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC)((sc->sc_cur_regwin->rw_type == 0x812) ? (void)0 : __assert ("diagnostic ", "/usr/src/sys/dev/ic/bwi.c", 9436, "sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC" )); |
| 9437 | mac = (struct bwi_mac *)sc->sc_cur_regwin; |
| 9438 | |
| 9439 | bwi_mac_updateslot(mac, (ic->ic_flags & IEEE80211_F_SHSLOT0x00020000)); |
| 9440 | } |
| 9441 | |
| 9442 | void |
| 9443 | bwi_calibrate(void *xsc) |
| 9444 | { |
| 9445 | struct bwi_softc *sc = xsc; |
| 9446 | struct ieee80211com *ic = &sc->sc_ic; |
| 9447 | int s; |
| 9448 | |
| 9449 | s = splnet()splraise(0x4); |
| 9450 | |
| 9451 | if (ic->ic_state == IEEE80211_S_RUN) { |
| 9452 | struct bwi_mac *mac; |
| 9453 | |
| 9454 | KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC)((sc->sc_cur_regwin->rw_type == 0x812) ? (void)0 : __assert ("diagnostic ", "/usr/src/sys/dev/ic/bwi.c", 9454, "sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC" )); |
| 9455 | mac = (struct bwi_mac *)sc->sc_cur_regwin; |
| 9456 | |
| 9457 | if (ic->ic_opmode != IEEE80211_M_MONITOR) { |
| 9458 | bwi_mac_calibrate_txpower(mac, sc->sc_txpwrcb_type); |
| 9459 | sc->sc_txpwrcb_type = BWI_TXPWR_CALIB; |
| 9460 | } |
| 9461 | |
| 9462 | /* XXX 15 seconds */ |
| 9463 | timeout_add_sec(&sc->sc_calib_ch, 15); |
| 9464 | } |
| 9465 | |
| 9466 | splx(s)spllower(s); |
| 9467 | } |
| 9468 | |
| 9469 | int |
| 9470 | bwi_calc_rssi(struct bwi_softc *sc, const struct bwi_rxbuf_hdr *hdr) |
| 9471 | { |
| 9472 | struct bwi_mac *mac; |
| 9473 | |
| 9474 | KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC)((sc->sc_cur_regwin->rw_type == 0x812) ? (void)0 : __assert ("diagnostic ", "/usr/src/sys/dev/ic/bwi.c", 9474, "sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC" )); |
| 9475 | mac = (struct bwi_mac *)sc->sc_cur_regwin; |
| 9476 | |
| 9477 | return (bwi_rf_calc_rssi(mac, hdr)); |
| 9478 | } |