1235233Sbschmidt/*- 2235233Sbschmidt * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr> 3235233Sbschmidt * Copyright (c) 2012 Bernhard Schmidt <bschmidt@FreeBSD.org> 4235233Sbschmidt * 5235233Sbschmidt * Permission to use, copy, modify, and distribute this software for any 6235233Sbschmidt * purpose with or without fee is hereby granted, provided that the above 7235233Sbschmidt * copyright notice and this permission notice appear in all copies. 8235233Sbschmidt * 9235233Sbschmidt * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10235233Sbschmidt * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11235233Sbschmidt * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12235233Sbschmidt * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13235233Sbschmidt * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14235233Sbschmidt * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15235233Sbschmidt * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16235233Sbschmidt * 17235233Sbschmidt * $OpenBSD: rt2860.c,v 1.65 2010/10/23 14:24:54 damien Exp $ 18235233Sbschmidt */ 19235233Sbschmidt 20235233Sbschmidt#include <sys/cdefs.h> 21235233Sbschmidt__FBSDID("$FreeBSD: stable/11/sys/dev/ral/rt2860.c 351143 2019-08-16 21:03:55Z kevans $"); 22235233Sbschmidt 23235233Sbschmidt/*- 24278551Skevlo * Ralink Technology RT2860/RT3090/RT3390/RT3562/RT5390/RT5392 chipset driver 25235233Sbschmidt * http://www.ralinktech.com/ 26235233Sbschmidt */ 27235233Sbschmidt 28235233Sbschmidt#include <sys/param.h> 29235233Sbschmidt#include <sys/sysctl.h> 30235233Sbschmidt#include <sys/sockio.h> 31235233Sbschmidt#include <sys/mbuf.h> 32235233Sbschmidt#include <sys/kernel.h> 33235233Sbschmidt#include <sys/socket.h> 34235233Sbschmidt#include <sys/systm.h> 35235233Sbschmidt#include <sys/malloc.h> 36235233Sbschmidt#include <sys/lock.h> 37235233Sbschmidt#include <sys/mutex.h> 38235233Sbschmidt#include <sys/module.h> 39235233Sbschmidt#include <sys/bus.h> 40235233Sbschmidt#include <sys/endian.h> 41235233Sbschmidt#include <sys/firmware.h> 42235233Sbschmidt 43235233Sbschmidt#include <machine/bus.h> 44235233Sbschmidt#include <machine/resource.h> 45235233Sbschmidt#include <sys/rman.h> 46235233Sbschmidt 47235233Sbschmidt#include <net/bpf.h> 48235233Sbschmidt#include <net/if.h> 49257176Sglebius#include <net/if_var.h> 50235233Sbschmidt#include <net/if_arp.h> 51235233Sbschmidt#include <net/ethernet.h> 52235233Sbschmidt#include <net/if_dl.h> 53235233Sbschmidt#include <net/if_media.h> 54235233Sbschmidt#include <net/if_types.h> 55235233Sbschmidt 56235233Sbschmidt#include <net80211/ieee80211_var.h> 57235233Sbschmidt#include <net80211/ieee80211_radiotap.h> 58235233Sbschmidt#include <net80211/ieee80211_regdomain.h> 59235233Sbschmidt#include <net80211/ieee80211_ratectl.h> 60235233Sbschmidt 61235233Sbschmidt#include <netinet/in.h> 62235233Sbschmidt#include <netinet/in_systm.h> 63235233Sbschmidt#include <netinet/in_var.h> 64235233Sbschmidt#include <netinet/ip.h> 65235233Sbschmidt#include <netinet/if_ether.h> 66235233Sbschmidt 67235233Sbschmidt#include <dev/ral/rt2860reg.h> 68235233Sbschmidt#include <dev/ral/rt2860var.h> 69235233Sbschmidt 70235233Sbschmidt#define RAL_DEBUG 71235233Sbschmidt#ifdef RAL_DEBUG 72235233Sbschmidt#define DPRINTF(x) do { if (sc->sc_debug > 0) printf x; } while (0) 73235233Sbschmidt#define DPRINTFN(n, x) do { if (sc->sc_debug >= (n)) printf x; } while (0) 74235233Sbschmidt#else 75235233Sbschmidt#define DPRINTF(x) 76235233Sbschmidt#define DPRINTFN(n, x) 77235233Sbschmidt#endif 78235233Sbschmidt 79235233Sbschmidtstatic struct ieee80211vap *rt2860_vap_create(struct ieee80211com *, 80235233Sbschmidt const char [IFNAMSIZ], int, enum ieee80211_opmode, 81235233Sbschmidt int, const uint8_t [IEEE80211_ADDR_LEN], 82235233Sbschmidt const uint8_t [IEEE80211_ADDR_LEN]); 83235233Sbschmidtstatic void rt2860_vap_delete(struct ieee80211vap *); 84235233Sbschmidtstatic void rt2860_dma_map_addr(void *, bus_dma_segment_t *, int, int); 85235233Sbschmidtstatic int rt2860_alloc_tx_ring(struct rt2860_softc *, 86235233Sbschmidt struct rt2860_tx_ring *); 87235233Sbschmidtstatic void rt2860_reset_tx_ring(struct rt2860_softc *, 88235233Sbschmidt struct rt2860_tx_ring *); 89235233Sbschmidtstatic void rt2860_free_tx_ring(struct rt2860_softc *, 90235233Sbschmidt struct rt2860_tx_ring *); 91235233Sbschmidtstatic int rt2860_alloc_tx_pool(struct rt2860_softc *); 92235233Sbschmidtstatic void rt2860_free_tx_pool(struct rt2860_softc *); 93235233Sbschmidtstatic int rt2860_alloc_rx_ring(struct rt2860_softc *, 94235233Sbschmidt struct rt2860_rx_ring *); 95235233Sbschmidtstatic void rt2860_reset_rx_ring(struct rt2860_softc *, 96235233Sbschmidt struct rt2860_rx_ring *); 97235233Sbschmidtstatic void rt2860_free_rx_ring(struct rt2860_softc *, 98235233Sbschmidt struct rt2860_rx_ring *); 99235233Sbschmidtstatic void rt2860_updatestats(struct rt2860_softc *); 100235233Sbschmidtstatic void rt2860_newassoc(struct ieee80211_node *, int); 101235233Sbschmidtstatic void rt2860_node_free(struct ieee80211_node *); 102235233Sbschmidt#ifdef IEEE80211_HT 103235233Sbschmidtstatic int rt2860_ampdu_rx_start(struct ieee80211com *, 104235233Sbschmidt struct ieee80211_node *, uint8_t); 105235233Sbschmidtstatic void rt2860_ampdu_rx_stop(struct ieee80211com *, 106235233Sbschmidt struct ieee80211_node *, uint8_t); 107235233Sbschmidt#endif 108235233Sbschmidtstatic int rt2860_newstate(struct ieee80211vap *, enum ieee80211_state, 109235233Sbschmidt int); 110235233Sbschmidtstatic uint16_t rt3090_efuse_read_2(struct rt2860_softc *, uint16_t); 111235233Sbschmidtstatic uint16_t rt2860_eeprom_read_2(struct rt2860_softc *, uint16_t); 112235233Sbschmidtstatic void rt2860_intr_coherent(struct rt2860_softc *); 113235233Sbschmidtstatic void rt2860_drain_stats_fifo(struct rt2860_softc *); 114235233Sbschmidtstatic void rt2860_tx_intr(struct rt2860_softc *, int); 115235233Sbschmidtstatic void rt2860_rx_intr(struct rt2860_softc *); 116235233Sbschmidtstatic void rt2860_tbtt_intr(struct rt2860_softc *); 117235233Sbschmidtstatic void rt2860_gp_intr(struct rt2860_softc *); 118235233Sbschmidtstatic int rt2860_tx(struct rt2860_softc *, struct mbuf *, 119235233Sbschmidt struct ieee80211_node *); 120235233Sbschmidtstatic int rt2860_raw_xmit(struct ieee80211_node *, struct mbuf *, 121235233Sbschmidt const struct ieee80211_bpf_params *); 122235233Sbschmidtstatic int rt2860_tx_raw(struct rt2860_softc *, struct mbuf *, 123235233Sbschmidt struct ieee80211_node *, 124235233Sbschmidt const struct ieee80211_bpf_params *params); 125287197Sglebiusstatic int rt2860_transmit(struct ieee80211com *, struct mbuf *); 126287197Sglebiusstatic void rt2860_start(struct rt2860_softc *); 127235233Sbschmidtstatic void rt2860_watchdog(void *); 128287197Sglebiusstatic void rt2860_parent(struct ieee80211com *); 129235233Sbschmidtstatic void rt2860_mcu_bbp_write(struct rt2860_softc *, uint8_t, uint8_t); 130235233Sbschmidtstatic uint8_t rt2860_mcu_bbp_read(struct rt2860_softc *, uint8_t); 131235233Sbschmidtstatic void rt2860_rf_write(struct rt2860_softc *, uint8_t, uint32_t); 132235233Sbschmidtstatic uint8_t rt3090_rf_read(struct rt2860_softc *, uint8_t); 133235233Sbschmidtstatic void rt3090_rf_write(struct rt2860_softc *, uint8_t, uint8_t); 134235233Sbschmidtstatic int rt2860_mcu_cmd(struct rt2860_softc *, uint8_t, uint16_t, int); 135235233Sbschmidtstatic void rt2860_enable_mrr(struct rt2860_softc *); 136235233Sbschmidtstatic void rt2860_set_txpreamble(struct rt2860_softc *); 137235233Sbschmidtstatic void rt2860_set_basicrates(struct rt2860_softc *, 138235233Sbschmidt const struct ieee80211_rateset *); 139235233Sbschmidtstatic void rt2860_scan_start(struct ieee80211com *); 140235233Sbschmidtstatic void rt2860_scan_end(struct ieee80211com *); 141300752Savosstatic void rt2860_getradiocaps(struct ieee80211com *, int, int *, 142300752Savos struct ieee80211_channel[]); 143235233Sbschmidtstatic void rt2860_set_channel(struct ieee80211com *); 144235233Sbschmidtstatic void rt2860_select_chan_group(struct rt2860_softc *, int); 145235233Sbschmidtstatic void rt2860_set_chan(struct rt2860_softc *, u_int); 146235233Sbschmidtstatic void rt3090_set_chan(struct rt2860_softc *, u_int); 147278551Skevlostatic void rt5390_set_chan(struct rt2860_softc *, u_int); 148235233Sbschmidtstatic int rt3090_rf_init(struct rt2860_softc *); 149278551Skevlostatic void rt5390_rf_init(struct rt2860_softc *); 150235233Sbschmidtstatic void rt3090_rf_wakeup(struct rt2860_softc *); 151278551Skevlostatic void rt5390_rf_wakeup(struct rt2860_softc *); 152235233Sbschmidtstatic int rt3090_filter_calib(struct rt2860_softc *, uint8_t, uint8_t, 153235233Sbschmidt uint8_t *); 154235233Sbschmidtstatic void rt3090_rf_setup(struct rt2860_softc *); 155235233Sbschmidtstatic void rt2860_set_leds(struct rt2860_softc *, uint16_t); 156235233Sbschmidtstatic void rt2860_set_gp_timer(struct rt2860_softc *, int); 157235233Sbschmidtstatic void rt2860_set_bssid(struct rt2860_softc *, const uint8_t *); 158235233Sbschmidtstatic void rt2860_set_macaddr(struct rt2860_softc *, const uint8_t *); 159283540Sglebiusstatic void rt2860_update_promisc(struct ieee80211com *); 160283540Sglebiusstatic void rt2860_updateslot(struct ieee80211com *); 161287197Sglebiusstatic void rt2860_updateprot(struct rt2860_softc *); 162235233Sbschmidtstatic int rt2860_updateedca(struct ieee80211com *); 163235233Sbschmidt#ifdef HW_CRYPTO 164235233Sbschmidtstatic int rt2860_set_key(struct ieee80211com *, struct ieee80211_node *, 165235233Sbschmidt struct ieee80211_key *); 166235233Sbschmidtstatic void rt2860_delete_key(struct ieee80211com *, 167235233Sbschmidt struct ieee80211_node *, struct ieee80211_key *); 168235233Sbschmidt#endif 169235233Sbschmidtstatic int8_t rt2860_rssi2dbm(struct rt2860_softc *, uint8_t, uint8_t); 170300006Skevlostatic const char *rt2860_get_rf(uint16_t); 171235233Sbschmidtstatic int rt2860_read_eeprom(struct rt2860_softc *, 172235233Sbschmidt uint8_t macaddr[IEEE80211_ADDR_LEN]); 173235233Sbschmidtstatic int rt2860_bbp_init(struct rt2860_softc *); 174278551Skevlostatic void rt5390_bbp_init(struct rt2860_softc *); 175235233Sbschmidtstatic int rt2860_txrx_enable(struct rt2860_softc *); 176235233Sbschmidtstatic void rt2860_init(void *); 177235233Sbschmidtstatic void rt2860_init_locked(struct rt2860_softc *); 178235233Sbschmidtstatic void rt2860_stop(void *); 179235233Sbschmidtstatic void rt2860_stop_locked(struct rt2860_softc *); 180235233Sbschmidtstatic int rt2860_load_microcode(struct rt2860_softc *); 181235233Sbschmidt#ifdef NOT_YET 182235233Sbschmidtstatic void rt2860_calib(struct rt2860_softc *); 183235233Sbschmidt#endif 184235233Sbschmidtstatic void rt3090_set_rx_antenna(struct rt2860_softc *, int); 185235233Sbschmidtstatic void rt2860_switch_chan(struct rt2860_softc *, 186235233Sbschmidt struct ieee80211_channel *); 187235233Sbschmidtstatic int rt2860_setup_beacon(struct rt2860_softc *, 188235233Sbschmidt struct ieee80211vap *); 189235233Sbschmidtstatic void rt2860_enable_tsf_sync(struct rt2860_softc *); 190235233Sbschmidt 191235233Sbschmidtstatic const struct { 192235233Sbschmidt uint32_t reg; 193235233Sbschmidt uint32_t val; 194235233Sbschmidt} rt2860_def_mac[] = { 195235233Sbschmidt RT2860_DEF_MAC 196235233Sbschmidt}; 197235233Sbschmidt 198235233Sbschmidtstatic const struct { 199235233Sbschmidt uint8_t reg; 200235233Sbschmidt uint8_t val; 201235233Sbschmidt} rt2860_def_bbp[] = { 202235233Sbschmidt RT2860_DEF_BBP 203278551Skevlo}, rt5390_def_bbp[] = { 204278551Skevlo RT5390_DEF_BBP 205235233Sbschmidt}; 206235233Sbschmidt 207235233Sbschmidtstatic const struct rfprog { 208235233Sbschmidt uint8_t chan; 209235233Sbschmidt uint32_t r1, r2, r3, r4; 210235233Sbschmidt} rt2860_rf2850[] = { 211235233Sbschmidt RT2860_RF2850 212235233Sbschmidt}; 213235233Sbschmidt 214235233Sbschmidtstruct { 215235233Sbschmidt uint8_t n, r, k; 216235233Sbschmidt} rt3090_freqs[] = { 217235233Sbschmidt RT3070_RF3052 218235233Sbschmidt}; 219235233Sbschmidt 220235233Sbschmidtstatic const struct { 221235233Sbschmidt uint8_t reg; 222235233Sbschmidt uint8_t val; 223278551Skevlo} rt3090_def_rf[] = { 224235233Sbschmidt RT3070_DEF_RF 225278551Skevlo}, rt5390_def_rf[] = { 226278551Skevlo RT5390_DEF_RF 227278551Skevlo}, rt5392_def_rf[] = { 228278551Skevlo RT5392_DEF_RF 229235233Sbschmidt}; 230235233Sbschmidt 231300752Savosstatic const uint8_t rt2860_chan_5ghz[] = 232300752Savos { 36, 38, 40, 44, 46, 48, 52, 54, 56, 60, 62, 64, 100, 102, 104, 233300752Savos 108, 110, 112, 116, 118, 120, 124, 126, 128, 132, 134, 136, 140, 234300752Savos 149, 151, 153, 157, 159, 161, 165, 167, 169, 171, 173 }; 235300752Savos 236235233Sbschmidtint 237235233Sbschmidtrt2860_attach(device_t dev, int id) 238235233Sbschmidt{ 239235233Sbschmidt struct rt2860_softc *sc = device_get_softc(dev); 240287197Sglebius struct ieee80211com *ic = &sc->sc_ic; 241235233Sbschmidt uint32_t tmp; 242235233Sbschmidt int error, ntries, qid; 243235233Sbschmidt 244235233Sbschmidt sc->sc_dev = dev; 245235233Sbschmidt sc->sc_debug = 0; 246235233Sbschmidt 247235233Sbschmidt mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, 248235233Sbschmidt MTX_DEF | MTX_RECURSE); 249235233Sbschmidt 250235233Sbschmidt callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0); 251287197Sglebius mbufq_init(&sc->sc_snd, ifqmaxlen); 252235233Sbschmidt 253235233Sbschmidt /* wait for NIC to initialize */ 254235233Sbschmidt for (ntries = 0; ntries < 100; ntries++) { 255235233Sbschmidt tmp = RAL_READ(sc, RT2860_ASIC_VER_ID); 256235233Sbschmidt if (tmp != 0 && tmp != 0xffffffff) 257235233Sbschmidt break; 258235233Sbschmidt DELAY(10); 259235233Sbschmidt } 260235233Sbschmidt if (ntries == 100) { 261235233Sbschmidt device_printf(sc->sc_dev, 262235233Sbschmidt "timeout waiting for NIC to initialize\n"); 263235233Sbschmidt error = EIO; 264235233Sbschmidt goto fail1; 265235233Sbschmidt } 266235233Sbschmidt sc->mac_ver = tmp >> 16; 267235233Sbschmidt sc->mac_rev = tmp & 0xffff; 268235233Sbschmidt 269235233Sbschmidt if (sc->mac_ver != 0x2860 && 270235233Sbschmidt (id == 0x0681 || id == 0x0781 || id == 0x1059)) 271235233Sbschmidt sc->sc_flags |= RT2860_ADVANCED_PS; 272235233Sbschmidt 273235233Sbschmidt /* retrieve RF rev. no and various other things from EEPROM */ 274287197Sglebius rt2860_read_eeprom(sc, ic->ic_macaddr); 275278551Skevlo device_printf(sc->sc_dev, "MAC/BBP RT%X (rev 0x%04X), " 276278551Skevlo "RF %s (MIMO %dT%dR), address %6D\n", 277278551Skevlo sc->mac_ver, sc->mac_rev, rt2860_get_rf(sc->rf_rev), 278287197Sglebius sc->ntxchains, sc->nrxchains, ic->ic_macaddr, ":"); 279235233Sbschmidt 280235233Sbschmidt /* 281235233Sbschmidt * Allocate Tx (4 EDCAs + HCCA + Mgt) and Rx rings. 282235233Sbschmidt */ 283235233Sbschmidt for (qid = 0; qid < 6; qid++) { 284235233Sbschmidt if ((error = rt2860_alloc_tx_ring(sc, &sc->txq[qid])) != 0) { 285235233Sbschmidt device_printf(sc->sc_dev, 286235233Sbschmidt "could not allocate Tx ring %d\n", qid); 287235233Sbschmidt goto fail2; 288235233Sbschmidt } 289235233Sbschmidt } 290235233Sbschmidt 291235233Sbschmidt if ((error = rt2860_alloc_rx_ring(sc, &sc->rxq)) != 0) { 292235233Sbschmidt device_printf(sc->sc_dev, "could not allocate Rx ring\n"); 293235233Sbschmidt goto fail2; 294235233Sbschmidt } 295235233Sbschmidt 296235233Sbschmidt if ((error = rt2860_alloc_tx_pool(sc)) != 0) { 297235233Sbschmidt device_printf(sc->sc_dev, "could not allocate Tx pool\n"); 298235233Sbschmidt goto fail3; 299235233Sbschmidt } 300235233Sbschmidt 301235233Sbschmidt /* mgmt ring is broken on RT2860C, use EDCA AC VO ring instead */ 302235233Sbschmidt sc->mgtqid = (sc->mac_ver == 0x2860 && sc->mac_rev == 0x0100) ? 303235233Sbschmidt WME_AC_VO : 5; 304235233Sbschmidt 305283537Sglebius ic->ic_softc = sc; 306283527Sglebius ic->ic_name = device_get_nameunit(dev); 307235233Sbschmidt ic->ic_opmode = IEEE80211_M_STA; 308235233Sbschmidt ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ 309235233Sbschmidt 310235233Sbschmidt /* set device capabilities */ 311235233Sbschmidt ic->ic_caps = 312235233Sbschmidt IEEE80211_C_STA /* station mode */ 313235233Sbschmidt | IEEE80211_C_IBSS /* ibss, nee adhoc, mode */ 314235233Sbschmidt | IEEE80211_C_HOSTAP /* hostap mode */ 315235233Sbschmidt | IEEE80211_C_MONITOR /* monitor mode */ 316235233Sbschmidt | IEEE80211_C_AHDEMO /* adhoc demo mode */ 317235233Sbschmidt | IEEE80211_C_WDS /* 4-address traffic works */ 318235233Sbschmidt | IEEE80211_C_MBSS /* mesh point link mode */ 319235233Sbschmidt | IEEE80211_C_SHPREAMBLE /* short preamble supported */ 320235233Sbschmidt | IEEE80211_C_SHSLOT /* short slot time supported */ 321235233Sbschmidt | IEEE80211_C_WPA /* capable of WPA1+WPA2 */ 322235233Sbschmidt#if 0 323235233Sbschmidt | IEEE80211_C_BGSCAN /* capable of bg scanning */ 324235233Sbschmidt#endif 325235233Sbschmidt | IEEE80211_C_WME /* 802.11e */ 326235233Sbschmidt ; 327235233Sbschmidt 328300752Savos rt2860_getradiocaps(ic, IEEE80211_CHAN_MAX, &ic->ic_nchans, 329300752Savos ic->ic_channels); 330235233Sbschmidt 331287197Sglebius ieee80211_ifattach(ic); 332235233Sbschmidt 333235233Sbschmidt ic->ic_wme.wme_update = rt2860_updateedca; 334235233Sbschmidt ic->ic_scan_start = rt2860_scan_start; 335235233Sbschmidt ic->ic_scan_end = rt2860_scan_end; 336300752Savos ic->ic_getradiocaps = rt2860_getradiocaps; 337235233Sbschmidt ic->ic_set_channel = rt2860_set_channel; 338235233Sbschmidt ic->ic_updateslot = rt2860_updateslot; 339235233Sbschmidt ic->ic_update_promisc = rt2860_update_promisc; 340235233Sbschmidt ic->ic_raw_xmit = rt2860_raw_xmit; 341235233Sbschmidt sc->sc_node_free = ic->ic_node_free; 342235233Sbschmidt ic->ic_node_free = rt2860_node_free; 343235233Sbschmidt ic->ic_newassoc = rt2860_newassoc; 344287197Sglebius ic->ic_transmit = rt2860_transmit; 345287197Sglebius ic->ic_parent = rt2860_parent; 346235233Sbschmidt ic->ic_vap_create = rt2860_vap_create; 347235233Sbschmidt ic->ic_vap_delete = rt2860_vap_delete; 348235233Sbschmidt 349235233Sbschmidt ieee80211_radiotap_attach(ic, 350235233Sbschmidt &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), 351235233Sbschmidt RT2860_TX_RADIOTAP_PRESENT, 352235233Sbschmidt &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap), 353235233Sbschmidt RT2860_RX_RADIOTAP_PRESENT); 354235233Sbschmidt 355235233Sbschmidt#ifdef RAL_DEBUG 356235233Sbschmidt SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), 357235233Sbschmidt SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 358235233Sbschmidt "debug", CTLFLAG_RW, &sc->sc_debug, 0, "debug msgs"); 359235233Sbschmidt#endif 360235233Sbschmidt if (bootverbose) 361235233Sbschmidt ieee80211_announce(ic); 362235233Sbschmidt 363235233Sbschmidt return 0; 364235233Sbschmidt 365235233Sbschmidtfail3: rt2860_free_rx_ring(sc, &sc->rxq); 366235233Sbschmidtfail2: while (--qid >= 0) 367235233Sbschmidt rt2860_free_tx_ring(sc, &sc->txq[qid]); 368235233Sbschmidtfail1: mtx_destroy(&sc->sc_mtx); 369235233Sbschmidt return error; 370235233Sbschmidt} 371235233Sbschmidt 372235233Sbschmidtint 373235233Sbschmidtrt2860_detach(void *xsc) 374235233Sbschmidt{ 375235233Sbschmidt struct rt2860_softc *sc = xsc; 376287197Sglebius struct ieee80211com *ic = &sc->sc_ic; 377235233Sbschmidt int qid; 378235233Sbschmidt 379235233Sbschmidt RAL_LOCK(sc); 380235233Sbschmidt rt2860_stop_locked(sc); 381235233Sbschmidt RAL_UNLOCK(sc); 382235233Sbschmidt 383235233Sbschmidt ieee80211_ifdetach(ic); 384287197Sglebius mbufq_drain(&sc->sc_snd); 385235233Sbschmidt for (qid = 0; qid < 6; qid++) 386235233Sbschmidt rt2860_free_tx_ring(sc, &sc->txq[qid]); 387235233Sbschmidt rt2860_free_rx_ring(sc, &sc->rxq); 388235233Sbschmidt rt2860_free_tx_pool(sc); 389235233Sbschmidt 390235233Sbschmidt mtx_destroy(&sc->sc_mtx); 391235233Sbschmidt 392235233Sbschmidt return 0; 393235233Sbschmidt} 394235233Sbschmidt 395235233Sbschmidtvoid 396235233Sbschmidtrt2860_shutdown(void *xsc) 397235233Sbschmidt{ 398235233Sbschmidt struct rt2860_softc *sc = xsc; 399235233Sbschmidt 400235233Sbschmidt rt2860_stop(sc); 401235233Sbschmidt} 402235233Sbschmidt 403235233Sbschmidtvoid 404235233Sbschmidtrt2860_suspend(void *xsc) 405235233Sbschmidt{ 406235233Sbschmidt struct rt2860_softc *sc = xsc; 407235233Sbschmidt 408235233Sbschmidt rt2860_stop(sc); 409235233Sbschmidt} 410235233Sbschmidt 411235233Sbschmidtvoid 412235233Sbschmidtrt2860_resume(void *xsc) 413235233Sbschmidt{ 414235233Sbschmidt struct rt2860_softc *sc = xsc; 415235233Sbschmidt 416287197Sglebius if (sc->sc_ic.ic_nrunning > 0) 417235233Sbschmidt rt2860_init(sc); 418235233Sbschmidt} 419235233Sbschmidt 420235233Sbschmidtstatic struct ieee80211vap * 421235233Sbschmidtrt2860_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, 422235233Sbschmidt enum ieee80211_opmode opmode, int flags, 423235233Sbschmidt const uint8_t bssid[IEEE80211_ADDR_LEN], 424235233Sbschmidt const uint8_t mac[IEEE80211_ADDR_LEN]) 425235233Sbschmidt{ 426287197Sglebius struct rt2860_softc *sc = ic->ic_softc; 427235233Sbschmidt struct rt2860_vap *rvp; 428235233Sbschmidt struct ieee80211vap *vap; 429235233Sbschmidt 430235233Sbschmidt switch (opmode) { 431235233Sbschmidt case IEEE80211_M_STA: 432235233Sbschmidt case IEEE80211_M_IBSS: 433235233Sbschmidt case IEEE80211_M_AHDEMO: 434235233Sbschmidt case IEEE80211_M_MONITOR: 435235233Sbschmidt case IEEE80211_M_HOSTAP: 436235233Sbschmidt case IEEE80211_M_MBSS: 437235233Sbschmidt /* XXXRP: TBD */ 438235233Sbschmidt if (!TAILQ_EMPTY(&ic->ic_vaps)) { 439287197Sglebius device_printf(sc->sc_dev, "only 1 vap supported\n"); 440235233Sbschmidt return NULL; 441235233Sbschmidt } 442235233Sbschmidt if (opmode == IEEE80211_M_STA) 443235233Sbschmidt flags |= IEEE80211_CLONE_NOBEACONS; 444235233Sbschmidt break; 445235233Sbschmidt case IEEE80211_M_WDS: 446235233Sbschmidt if (TAILQ_EMPTY(&ic->ic_vaps) || 447235233Sbschmidt ic->ic_opmode != IEEE80211_M_HOSTAP) { 448287197Sglebius device_printf(sc->sc_dev, 449287197Sglebius "wds only supported in ap mode\n"); 450235233Sbschmidt return NULL; 451235233Sbschmidt } 452235233Sbschmidt /* 453235233Sbschmidt * Silently remove any request for a unique 454235233Sbschmidt * bssid; WDS vap's always share the local 455235233Sbschmidt * mac address. 456235233Sbschmidt */ 457235233Sbschmidt flags &= ~IEEE80211_CLONE_BSSID; 458235233Sbschmidt break; 459235233Sbschmidt default: 460287197Sglebius device_printf(sc->sc_dev, "unknown opmode %d\n", opmode); 461235233Sbschmidt return NULL; 462235233Sbschmidt } 463287197Sglebius rvp = malloc(sizeof(struct rt2860_vap), M_80211_VAP, M_WAITOK | M_ZERO); 464235233Sbschmidt vap = &rvp->ral_vap; 465287197Sglebius ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid); 466235233Sbschmidt 467235233Sbschmidt /* override state transition machine */ 468235233Sbschmidt rvp->ral_newstate = vap->iv_newstate; 469235233Sbschmidt vap->iv_newstate = rt2860_newstate; 470235233Sbschmidt#if 0 471235233Sbschmidt vap->iv_update_beacon = rt2860_beacon_update; 472235233Sbschmidt#endif 473235233Sbschmidt 474235233Sbschmidt /* HW supports up to 255 STAs (0-254) in HostAP and IBSS modes */ 475235233Sbschmidt vap->iv_max_aid = min(IEEE80211_AID_MAX, RT2860_WCID_MAX); 476235233Sbschmidt 477235233Sbschmidt ieee80211_ratectl_init(vap); 478235233Sbschmidt /* complete setup */ 479287197Sglebius ieee80211_vap_attach(vap, ieee80211_media_change, 480287197Sglebius ieee80211_media_status, mac); 481235233Sbschmidt if (TAILQ_FIRST(&ic->ic_vaps) == vap) 482235233Sbschmidt ic->ic_opmode = opmode; 483235233Sbschmidt return vap; 484235233Sbschmidt} 485235233Sbschmidt 486235233Sbschmidtstatic void 487235233Sbschmidtrt2860_vap_delete(struct ieee80211vap *vap) 488235233Sbschmidt{ 489235233Sbschmidt struct rt2860_vap *rvp = RT2860_VAP(vap); 490235233Sbschmidt 491235233Sbschmidt ieee80211_ratectl_deinit(vap); 492235233Sbschmidt ieee80211_vap_detach(vap); 493235233Sbschmidt free(rvp, M_80211_VAP); 494235233Sbschmidt} 495235233Sbschmidt 496235233Sbschmidtstatic void 497235233Sbschmidtrt2860_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error) 498235233Sbschmidt{ 499235233Sbschmidt if (error != 0) 500235233Sbschmidt return; 501235233Sbschmidt 502235233Sbschmidt KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); 503235233Sbschmidt 504235233Sbschmidt *(bus_addr_t *)arg = segs[0].ds_addr; 505235233Sbschmidt} 506235233Sbschmidt 507235233Sbschmidt 508235233Sbschmidtstatic int 509235233Sbschmidtrt2860_alloc_tx_ring(struct rt2860_softc *sc, struct rt2860_tx_ring *ring) 510235233Sbschmidt{ 511235233Sbschmidt int size, error; 512235233Sbschmidt 513235233Sbschmidt size = RT2860_TX_RING_COUNT * sizeof (struct rt2860_txd); 514235233Sbschmidt 515235233Sbschmidt error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 16, 0, 516235233Sbschmidt BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 517235233Sbschmidt size, 1, size, 0, NULL, NULL, &ring->desc_dmat); 518235233Sbschmidt if (error != 0) { 519290133Skevlo device_printf(sc->sc_dev, "could not create desc DMA tag\n"); 520235233Sbschmidt goto fail; 521235233Sbschmidt } 522235233Sbschmidt 523235233Sbschmidt error = bus_dmamem_alloc(ring->desc_dmat, (void **)&ring->txd, 524235233Sbschmidt BUS_DMA_NOWAIT | BUS_DMA_ZERO, &ring->desc_map); 525235233Sbschmidt if (error != 0) { 526235233Sbschmidt device_printf(sc->sc_dev, "could not allocate DMA memory\n"); 527235233Sbschmidt goto fail; 528235233Sbschmidt } 529235233Sbschmidt 530235233Sbschmidt error = bus_dmamap_load(ring->desc_dmat, ring->desc_map, ring->txd, 531235233Sbschmidt size, rt2860_dma_map_addr, &ring->paddr, 0); 532235233Sbschmidt if (error != 0) { 533235233Sbschmidt device_printf(sc->sc_dev, "could not load desc DMA map\n"); 534235233Sbschmidt goto fail; 535235233Sbschmidt } 536235233Sbschmidt 537235233Sbschmidt bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_PREWRITE); 538235233Sbschmidt 539235233Sbschmidt return 0; 540235233Sbschmidt 541235233Sbschmidtfail: rt2860_free_tx_ring(sc, ring); 542235233Sbschmidt return error; 543235233Sbschmidt} 544235233Sbschmidt 545235233Sbschmidtvoid 546235233Sbschmidtrt2860_reset_tx_ring(struct rt2860_softc *sc, struct rt2860_tx_ring *ring) 547235233Sbschmidt{ 548235233Sbschmidt struct rt2860_tx_data *data; 549235233Sbschmidt int i; 550235233Sbschmidt 551235233Sbschmidt for (i = 0; i < RT2860_TX_RING_COUNT; i++) { 552235233Sbschmidt if ((data = ring->data[i]) == NULL) 553235233Sbschmidt continue; /* nothing mapped in this slot */ 554235233Sbschmidt 555235233Sbschmidt if (data->m != NULL) { 556235233Sbschmidt bus_dmamap_sync(sc->txwi_dmat, data->map, 557235233Sbschmidt BUS_DMASYNC_POSTWRITE); 558235233Sbschmidt bus_dmamap_unload(sc->txwi_dmat, data->map); 559235233Sbschmidt m_freem(data->m); 560235233Sbschmidt data->m = NULL; 561235233Sbschmidt } 562235233Sbschmidt if (data->ni != NULL) { 563235233Sbschmidt ieee80211_free_node(data->ni); 564235233Sbschmidt data->ni = NULL; 565235233Sbschmidt } 566235233Sbschmidt 567235233Sbschmidt SLIST_INSERT_HEAD(&sc->data_pool, data, next); 568235233Sbschmidt ring->data[i] = NULL; 569235233Sbschmidt } 570235233Sbschmidt 571235233Sbschmidt ring->queued = 0; 572235233Sbschmidt ring->cur = ring->next = 0; 573235233Sbschmidt} 574235233Sbschmidt 575235233Sbschmidtvoid 576235233Sbschmidtrt2860_free_tx_ring(struct rt2860_softc *sc, struct rt2860_tx_ring *ring) 577235233Sbschmidt{ 578235233Sbschmidt struct rt2860_tx_data *data; 579235233Sbschmidt int i; 580235233Sbschmidt 581235233Sbschmidt if (ring->txd != NULL) { 582235233Sbschmidt bus_dmamap_sync(ring->desc_dmat, ring->desc_map, 583235233Sbschmidt BUS_DMASYNC_POSTWRITE); 584235233Sbschmidt bus_dmamap_unload(ring->desc_dmat, ring->desc_map); 585235233Sbschmidt bus_dmamem_free(ring->desc_dmat, ring->txd, ring->desc_map); 586235233Sbschmidt } 587235233Sbschmidt if (ring->desc_dmat != NULL) 588235233Sbschmidt bus_dma_tag_destroy(ring->desc_dmat); 589235233Sbschmidt 590235233Sbschmidt for (i = 0; i < RT2860_TX_RING_COUNT; i++) { 591235233Sbschmidt if ((data = ring->data[i]) == NULL) 592235233Sbschmidt continue; /* nothing mapped in this slot */ 593235233Sbschmidt 594235233Sbschmidt if (data->m != NULL) { 595235233Sbschmidt bus_dmamap_sync(sc->txwi_dmat, data->map, 596235233Sbschmidt BUS_DMASYNC_POSTWRITE); 597235233Sbschmidt bus_dmamap_unload(sc->txwi_dmat, data->map); 598235233Sbschmidt m_freem(data->m); 599235233Sbschmidt } 600235233Sbschmidt if (data->ni != NULL) 601235233Sbschmidt ieee80211_free_node(data->ni); 602235233Sbschmidt 603235233Sbschmidt SLIST_INSERT_HEAD(&sc->data_pool, data, next); 604235233Sbschmidt } 605235233Sbschmidt} 606235233Sbschmidt 607235233Sbschmidt/* 608235233Sbschmidt * Allocate a pool of TX Wireless Information blocks. 609235233Sbschmidt */ 610235233Sbschmidtint 611235233Sbschmidtrt2860_alloc_tx_pool(struct rt2860_softc *sc) 612235233Sbschmidt{ 613235233Sbschmidt caddr_t vaddr; 614235233Sbschmidt bus_addr_t paddr; 615235233Sbschmidt int i, size, error; 616235233Sbschmidt 617235233Sbschmidt size = RT2860_TX_POOL_COUNT * RT2860_TXWI_DMASZ; 618235233Sbschmidt 619235233Sbschmidt /* init data_pool early in case of failure.. */ 620235233Sbschmidt SLIST_INIT(&sc->data_pool); 621235233Sbschmidt 622235233Sbschmidt error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, 623235233Sbschmidt BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 624235233Sbschmidt size, 1, size, 0, NULL, NULL, &sc->txwi_dmat); 625235233Sbschmidt if (error != 0) { 626235233Sbschmidt device_printf(sc->sc_dev, "could not create txwi DMA tag\n"); 627235233Sbschmidt goto fail; 628235233Sbschmidt } 629235233Sbschmidt 630235233Sbschmidt error = bus_dmamem_alloc(sc->txwi_dmat, (void **)&sc->txwi_vaddr, 631235233Sbschmidt BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sc->txwi_map); 632235233Sbschmidt if (error != 0) { 633235233Sbschmidt device_printf(sc->sc_dev, "could not allocate DMA memory\n"); 634235233Sbschmidt goto fail; 635235233Sbschmidt } 636235233Sbschmidt 637235233Sbschmidt error = bus_dmamap_load(sc->txwi_dmat, sc->txwi_map, 638235233Sbschmidt sc->txwi_vaddr, size, rt2860_dma_map_addr, &paddr, 0); 639235233Sbschmidt if (error != 0) { 640235233Sbschmidt device_printf(sc->sc_dev, "could not load txwi DMA map\n"); 641235233Sbschmidt goto fail; 642235233Sbschmidt } 643235233Sbschmidt 644235233Sbschmidt bus_dmamap_sync(sc->txwi_dmat, sc->txwi_map, BUS_DMASYNC_PREWRITE); 645235233Sbschmidt 646235233Sbschmidt vaddr = sc->txwi_vaddr; 647235233Sbschmidt for (i = 0; i < RT2860_TX_POOL_COUNT; i++) { 648235233Sbschmidt struct rt2860_tx_data *data = &sc->data[i]; 649235233Sbschmidt 650235233Sbschmidt error = bus_dmamap_create(sc->txwi_dmat, 0, &data->map); 651235233Sbschmidt if (error != 0) { 652235233Sbschmidt device_printf(sc->sc_dev, "could not create DMA map\n"); 653235233Sbschmidt goto fail; 654235233Sbschmidt } 655235233Sbschmidt data->txwi = (struct rt2860_txwi *)vaddr; 656235233Sbschmidt data->paddr = paddr; 657235233Sbschmidt vaddr += RT2860_TXWI_DMASZ; 658235233Sbschmidt paddr += RT2860_TXWI_DMASZ; 659235233Sbschmidt 660235233Sbschmidt SLIST_INSERT_HEAD(&sc->data_pool, data, next); 661235233Sbschmidt } 662235233Sbschmidt 663235233Sbschmidt return 0; 664235233Sbschmidt 665235233Sbschmidtfail: rt2860_free_tx_pool(sc); 666235233Sbschmidt return error; 667235233Sbschmidt} 668235233Sbschmidt 669235233Sbschmidtvoid 670235233Sbschmidtrt2860_free_tx_pool(struct rt2860_softc *sc) 671235233Sbschmidt{ 672235233Sbschmidt if (sc->txwi_vaddr != NULL) { 673235233Sbschmidt bus_dmamap_sync(sc->txwi_dmat, sc->txwi_map, 674235233Sbschmidt BUS_DMASYNC_POSTWRITE); 675235233Sbschmidt bus_dmamap_unload(sc->txwi_dmat, sc->txwi_map); 676235233Sbschmidt bus_dmamem_free(sc->txwi_dmat, sc->txwi_vaddr, sc->txwi_map); 677235233Sbschmidt } 678235233Sbschmidt if (sc->txwi_dmat != NULL) 679235233Sbschmidt bus_dma_tag_destroy(sc->txwi_dmat); 680235233Sbschmidt 681235233Sbschmidt while (!SLIST_EMPTY(&sc->data_pool)) { 682235233Sbschmidt struct rt2860_tx_data *data; 683235233Sbschmidt data = SLIST_FIRST(&sc->data_pool); 684235233Sbschmidt bus_dmamap_destroy(sc->txwi_dmat, data->map); 685235233Sbschmidt SLIST_REMOVE_HEAD(&sc->data_pool, next); 686235233Sbschmidt } 687235233Sbschmidt} 688235233Sbschmidt 689235233Sbschmidtint 690235233Sbschmidtrt2860_alloc_rx_ring(struct rt2860_softc *sc, struct rt2860_rx_ring *ring) 691235233Sbschmidt{ 692235233Sbschmidt bus_addr_t physaddr; 693235233Sbschmidt int i, size, error; 694235233Sbschmidt 695235233Sbschmidt size = RT2860_RX_RING_COUNT * sizeof (struct rt2860_rxd); 696235233Sbschmidt 697235233Sbschmidt error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 16, 0, 698235233Sbschmidt BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 699235233Sbschmidt size, 1, size, 0, NULL, NULL, &ring->desc_dmat); 700235233Sbschmidt if (error != 0) { 701235233Sbschmidt device_printf(sc->sc_dev, "could not create desc DMA tag\n"); 702235233Sbschmidt goto fail; 703235233Sbschmidt } 704235233Sbschmidt 705235233Sbschmidt error = bus_dmamem_alloc(ring->desc_dmat, (void **)&ring->rxd, 706235233Sbschmidt BUS_DMA_NOWAIT | BUS_DMA_ZERO, &ring->desc_map); 707235233Sbschmidt if (error != 0) { 708235233Sbschmidt device_printf(sc->sc_dev, "could not allocate DMA memory\n"); 709235233Sbschmidt goto fail; 710235233Sbschmidt } 711235233Sbschmidt 712235233Sbschmidt error = bus_dmamap_load(ring->desc_dmat, ring->desc_map, ring->rxd, 713235233Sbschmidt size, rt2860_dma_map_addr, &ring->paddr, 0); 714235233Sbschmidt if (error != 0) { 715235233Sbschmidt device_printf(sc->sc_dev, "could not load desc DMA map\n"); 716235233Sbschmidt goto fail; 717235233Sbschmidt } 718235233Sbschmidt 719235233Sbschmidt error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, 720235233Sbschmidt BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 721235233Sbschmidt 1, MCLBYTES, 0, NULL, NULL, &ring->data_dmat); 722235233Sbschmidt if (error != 0) { 723235233Sbschmidt device_printf(sc->sc_dev, "could not create data DMA tag\n"); 724235233Sbschmidt goto fail; 725235233Sbschmidt } 726235233Sbschmidt 727235233Sbschmidt for (i = 0; i < RT2860_RX_RING_COUNT; i++) { 728235233Sbschmidt struct rt2860_rx_data *data = &ring->data[i]; 729235233Sbschmidt struct rt2860_rxd *rxd = &ring->rxd[i]; 730235233Sbschmidt 731235233Sbschmidt error = bus_dmamap_create(ring->data_dmat, 0, &data->map); 732235233Sbschmidt if (error != 0) { 733235233Sbschmidt device_printf(sc->sc_dev, "could not create DMA map\n"); 734235233Sbschmidt goto fail; 735235233Sbschmidt } 736235233Sbschmidt 737243857Sglebius data->m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 738235233Sbschmidt if (data->m == NULL) { 739235233Sbschmidt device_printf(sc->sc_dev, 740235233Sbschmidt "could not allocate rx mbuf\n"); 741235233Sbschmidt error = ENOMEM; 742235233Sbschmidt goto fail; 743235233Sbschmidt } 744235233Sbschmidt 745235233Sbschmidt error = bus_dmamap_load(ring->data_dmat, data->map, 746235233Sbschmidt mtod(data->m, void *), MCLBYTES, rt2860_dma_map_addr, 747235233Sbschmidt &physaddr, 0); 748235233Sbschmidt if (error != 0) { 749235233Sbschmidt device_printf(sc->sc_dev, 750235233Sbschmidt "could not load rx buf DMA map"); 751235233Sbschmidt goto fail; 752235233Sbschmidt } 753235233Sbschmidt 754235233Sbschmidt rxd->sdp0 = htole32(physaddr); 755235233Sbschmidt rxd->sdl0 = htole16(MCLBYTES); 756235233Sbschmidt } 757235233Sbschmidt 758235233Sbschmidt bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_PREWRITE); 759235233Sbschmidt 760235233Sbschmidt return 0; 761235233Sbschmidt 762235233Sbschmidtfail: rt2860_free_rx_ring(sc, ring); 763235233Sbschmidt return error; 764235233Sbschmidt} 765235233Sbschmidt 766235233Sbschmidtvoid 767235233Sbschmidtrt2860_reset_rx_ring(struct rt2860_softc *sc, struct rt2860_rx_ring *ring) 768235233Sbschmidt{ 769235233Sbschmidt int i; 770235233Sbschmidt 771235233Sbschmidt for (i = 0; i < RT2860_RX_RING_COUNT; i++) 772235233Sbschmidt ring->rxd[i].sdl0 &= ~htole16(RT2860_RX_DDONE); 773235233Sbschmidt 774235233Sbschmidt bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_PREWRITE); 775235233Sbschmidt 776235233Sbschmidt ring->cur = 0; 777235233Sbschmidt} 778235233Sbschmidt 779235233Sbschmidtvoid 780235233Sbschmidtrt2860_free_rx_ring(struct rt2860_softc *sc, struct rt2860_rx_ring *ring) 781235233Sbschmidt{ 782235233Sbschmidt int i; 783235233Sbschmidt 784235233Sbschmidt if (ring->rxd != NULL) { 785235233Sbschmidt bus_dmamap_sync(ring->desc_dmat, ring->desc_map, 786235233Sbschmidt BUS_DMASYNC_POSTWRITE); 787235233Sbschmidt bus_dmamap_unload(ring->desc_dmat, ring->desc_map); 788235233Sbschmidt bus_dmamem_free(ring->desc_dmat, ring->rxd, ring->desc_map); 789235233Sbschmidt } 790235233Sbschmidt if (ring->desc_dmat != NULL) 791235233Sbschmidt bus_dma_tag_destroy(ring->desc_dmat); 792235233Sbschmidt 793235233Sbschmidt for (i = 0; i < RT2860_RX_RING_COUNT; i++) { 794235233Sbschmidt struct rt2860_rx_data *data = &ring->data[i]; 795235233Sbschmidt 796235233Sbschmidt if (data->m != NULL) { 797235233Sbschmidt bus_dmamap_sync(ring->data_dmat, data->map, 798235233Sbschmidt BUS_DMASYNC_POSTREAD); 799235233Sbschmidt bus_dmamap_unload(ring->data_dmat, data->map); 800235233Sbschmidt m_freem(data->m); 801235233Sbschmidt } 802235233Sbschmidt if (data->map != NULL) 803235233Sbschmidt bus_dmamap_destroy(ring->data_dmat, data->map); 804235233Sbschmidt } 805235233Sbschmidt if (ring->data_dmat != NULL) 806235233Sbschmidt bus_dma_tag_destroy(ring->data_dmat); 807235233Sbschmidt} 808235233Sbschmidt 809235233Sbschmidtstatic void 810235233Sbschmidtrt2860_updatestats(struct rt2860_softc *sc) 811235233Sbschmidt{ 812287197Sglebius struct ieee80211com *ic = &sc->sc_ic; 813235233Sbschmidt 814235233Sbschmidt /* 815235233Sbschmidt * In IBSS or HostAP modes (when the hardware sends beacons), the 816235233Sbschmidt * MAC can run into a livelock and start sending CTS-to-self frames 817235233Sbschmidt * like crazy if protection is enabled. Fortunately, we can detect 818235233Sbschmidt * when such a situation occurs and reset the MAC. 819235233Sbschmidt */ 820235233Sbschmidt if (ic->ic_curmode != IEEE80211_M_STA) { 821235233Sbschmidt /* check if we're in a livelock situation.. */ 822235233Sbschmidt uint32_t tmp = RAL_READ(sc, RT2860_DEBUG); 823235233Sbschmidt if ((tmp & (1 << 29)) && (tmp & (1 << 7 | 1 << 5))) { 824235233Sbschmidt /* ..and reset MAC/BBP for a while.. */ 825235233Sbschmidt DPRINTF(("CTS-to-self livelock detected\n")); 826235233Sbschmidt RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, RT2860_MAC_SRST); 827235233Sbschmidt RAL_BARRIER_WRITE(sc); 828235233Sbschmidt DELAY(1); 829235233Sbschmidt RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, 830235233Sbschmidt RT2860_MAC_RX_EN | RT2860_MAC_TX_EN); 831235233Sbschmidt } 832235233Sbschmidt } 833235233Sbschmidt} 834235233Sbschmidt 835235233Sbschmidtstatic void 836235233Sbschmidtrt2860_newassoc(struct ieee80211_node *ni, int isnew) 837235233Sbschmidt{ 838235233Sbschmidt struct ieee80211com *ic = ni->ni_ic; 839287197Sglebius struct rt2860_softc *sc = ic->ic_softc; 840235233Sbschmidt uint8_t wcid; 841235233Sbschmidt 842235233Sbschmidt wcid = IEEE80211_AID(ni->ni_associd); 843235233Sbschmidt if (isnew && ni->ni_associd != 0) { 844235233Sbschmidt sc->wcid2ni[wcid] = ni; 845235233Sbschmidt 846235233Sbschmidt /* init WCID table entry */ 847235233Sbschmidt RAL_WRITE_REGION_1(sc, RT2860_WCID_ENTRY(wcid), 848235233Sbschmidt ni->ni_macaddr, IEEE80211_ADDR_LEN); 849235233Sbschmidt } 850235233Sbschmidt DPRINTF(("new assoc isnew=%d addr=%s WCID=%d\n", 851235233Sbschmidt isnew, ether_sprintf(ni->ni_macaddr), wcid)); 852235233Sbschmidt} 853235233Sbschmidt 854235233Sbschmidtstatic void 855235233Sbschmidtrt2860_node_free(struct ieee80211_node *ni) 856235233Sbschmidt{ 857235233Sbschmidt struct ieee80211com *ic = ni->ni_ic; 858287197Sglebius struct rt2860_softc *sc = ic->ic_softc; 859235233Sbschmidt uint8_t wcid; 860235233Sbschmidt 861235233Sbschmidt if (ni->ni_associd != 0) { 862235233Sbschmidt wcid = IEEE80211_AID(ni->ni_associd); 863235233Sbschmidt 864235233Sbschmidt /* clear Rx WCID search table entry */ 865235233Sbschmidt RAL_SET_REGION_4(sc, RT2860_WCID_ENTRY(wcid), 0, 2); 866235233Sbschmidt } 867235233Sbschmidt sc->sc_node_free(ni); 868235233Sbschmidt} 869235233Sbschmidt 870235233Sbschmidt#ifdef IEEE80211_HT 871235233Sbschmidtstatic int 872235233Sbschmidtrt2860_ampdu_rx_start(struct ieee80211com *ic, struct ieee80211_node *ni, 873235233Sbschmidt uint8_t tid) 874235233Sbschmidt{ 875235233Sbschmidt struct rt2860_softc *sc = ic->ic_softc; 876235233Sbschmidt uint8_t wcid = ((struct rt2860_node *)ni)->wcid; 877235233Sbschmidt uint32_t tmp; 878235233Sbschmidt 879235233Sbschmidt /* update BA session mask */ 880235233Sbschmidt tmp = RAL_READ(sc, RT2860_WCID_ENTRY(wcid) + 4); 881235233Sbschmidt tmp |= (1 << tid) << 16; 882235233Sbschmidt RAL_WRITE(sc, RT2860_WCID_ENTRY(wcid) + 4, tmp); 883235233Sbschmidt return 0; 884235233Sbschmidt} 885235233Sbschmidt 886235233Sbschmidtstatic void 887235233Sbschmidtrt2860_ampdu_rx_stop(struct ieee80211com *ic, struct ieee80211_node *ni, 888235233Sbschmidt uint8_t tid) 889235233Sbschmidt{ 890235233Sbschmidt struct rt2860_softc *sc = ic->ic_softc; 891235233Sbschmidt uint8_t wcid = ((struct rt2860_node *)ni)->wcid; 892235233Sbschmidt uint32_t tmp; 893235233Sbschmidt 894235233Sbschmidt /* update BA session mask */ 895235233Sbschmidt tmp = RAL_READ(sc, RT2860_WCID_ENTRY(wcid) + 4); 896235233Sbschmidt tmp &= ~((1 << tid) << 16); 897235233Sbschmidt RAL_WRITE(sc, RT2860_WCID_ENTRY(wcid) + 4, tmp); 898235233Sbschmidt} 899235233Sbschmidt#endif 900235233Sbschmidt 901301575Skevlostatic int 902235233Sbschmidtrt2860_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) 903235233Sbschmidt{ 904235233Sbschmidt struct rt2860_vap *rvp = RT2860_VAP(vap); 905235233Sbschmidt struct ieee80211com *ic = vap->iv_ic; 906287197Sglebius struct rt2860_softc *sc = ic->ic_softc; 907235233Sbschmidt uint32_t tmp; 908235233Sbschmidt int error; 909235233Sbschmidt 910235233Sbschmidt if (vap->iv_state == IEEE80211_S_RUN) { 911235233Sbschmidt /* turn link LED off */ 912235233Sbschmidt rt2860_set_leds(sc, RT2860_LED_RADIO); 913235233Sbschmidt } 914235233Sbschmidt 915235233Sbschmidt if (nstate == IEEE80211_S_INIT && vap->iv_state == IEEE80211_S_RUN) { 916235233Sbschmidt /* abort TSF synchronization */ 917235233Sbschmidt tmp = RAL_READ(sc, RT2860_BCN_TIME_CFG); 918235233Sbschmidt RAL_WRITE(sc, RT2860_BCN_TIME_CFG, 919235233Sbschmidt tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN | 920235233Sbschmidt RT2860_TBTT_TIMER_EN)); 921235233Sbschmidt } 922235233Sbschmidt 923235233Sbschmidt rt2860_set_gp_timer(sc, 0); 924235233Sbschmidt 925235233Sbschmidt error = rvp->ral_newstate(vap, nstate, arg); 926235233Sbschmidt if (error != 0) 927235233Sbschmidt return (error); 928235233Sbschmidt 929235233Sbschmidt if (nstate == IEEE80211_S_RUN) { 930235233Sbschmidt struct ieee80211_node *ni = vap->iv_bss; 931235233Sbschmidt 932235233Sbschmidt if (ic->ic_opmode != IEEE80211_M_MONITOR) { 933235233Sbschmidt rt2860_enable_mrr(sc); 934235233Sbschmidt rt2860_set_txpreamble(sc); 935235233Sbschmidt rt2860_set_basicrates(sc, &ni->ni_rates); 936235233Sbschmidt rt2860_set_bssid(sc, ni->ni_bssid); 937235233Sbschmidt } 938235233Sbschmidt 939235233Sbschmidt if (vap->iv_opmode == IEEE80211_M_HOSTAP || 940235233Sbschmidt vap->iv_opmode == IEEE80211_M_IBSS || 941235233Sbschmidt vap->iv_opmode == IEEE80211_M_MBSS) { 942235233Sbschmidt error = rt2860_setup_beacon(sc, vap); 943235233Sbschmidt if (error != 0) 944235233Sbschmidt return error; 945235233Sbschmidt } 946235233Sbschmidt 947235233Sbschmidt if (ic->ic_opmode != IEEE80211_M_MONITOR) { 948235233Sbschmidt rt2860_enable_tsf_sync(sc); 949235233Sbschmidt rt2860_set_gp_timer(sc, 500); 950235233Sbschmidt } 951235233Sbschmidt 952235233Sbschmidt /* turn link LED on */ 953235233Sbschmidt rt2860_set_leds(sc, RT2860_LED_RADIO | 954235233Sbschmidt (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan) ? 955235233Sbschmidt RT2860_LED_LINK_2GHZ : RT2860_LED_LINK_5GHZ)); 956235233Sbschmidt } 957235233Sbschmidt return error; 958235233Sbschmidt} 959235233Sbschmidt 960235233Sbschmidt/* Read 16-bit from eFUSE ROM (>=RT3071 only.) */ 961235233Sbschmidtstatic uint16_t 962235233Sbschmidtrt3090_efuse_read_2(struct rt2860_softc *sc, uint16_t addr) 963235233Sbschmidt{ 964235233Sbschmidt uint32_t tmp; 965235233Sbschmidt uint16_t reg; 966235233Sbschmidt int ntries; 967235233Sbschmidt 968235233Sbschmidt addr *= 2; 969235233Sbschmidt /*- 970235233Sbschmidt * Read one 16-byte block into registers EFUSE_DATA[0-3]: 971235233Sbschmidt * DATA0: F E D C 972235233Sbschmidt * DATA1: B A 9 8 973235233Sbschmidt * DATA2: 7 6 5 4 974235233Sbschmidt * DATA3: 3 2 1 0 975235233Sbschmidt */ 976235233Sbschmidt tmp = RAL_READ(sc, RT3070_EFUSE_CTRL); 977235233Sbschmidt tmp &= ~(RT3070_EFSROM_MODE_MASK | RT3070_EFSROM_AIN_MASK); 978235233Sbschmidt tmp |= (addr & ~0xf) << RT3070_EFSROM_AIN_SHIFT | RT3070_EFSROM_KICK; 979235233Sbschmidt RAL_WRITE(sc, RT3070_EFUSE_CTRL, tmp); 980235233Sbschmidt for (ntries = 0; ntries < 500; ntries++) { 981235233Sbschmidt tmp = RAL_READ(sc, RT3070_EFUSE_CTRL); 982235233Sbschmidt if (!(tmp & RT3070_EFSROM_KICK)) 983235233Sbschmidt break; 984235233Sbschmidt DELAY(2); 985235233Sbschmidt } 986235233Sbschmidt if (ntries == 500) 987235233Sbschmidt return 0xffff; 988235233Sbschmidt 989235233Sbschmidt if ((tmp & RT3070_EFUSE_AOUT_MASK) == RT3070_EFUSE_AOUT_MASK) 990235233Sbschmidt return 0xffff; /* address not found */ 991235233Sbschmidt 992235233Sbschmidt /* determine to which 32-bit register our 16-bit word belongs */ 993235233Sbschmidt reg = RT3070_EFUSE_DATA3 - (addr & 0xc); 994235233Sbschmidt tmp = RAL_READ(sc, reg); 995235233Sbschmidt 996235233Sbschmidt return (addr & 2) ? tmp >> 16 : tmp & 0xffff; 997235233Sbschmidt} 998235233Sbschmidt 999235233Sbschmidt/* 1000235233Sbschmidt * Read 16 bits at address 'addr' from the serial EEPROM (either 93C46, 1001235233Sbschmidt * 93C66 or 93C86). 1002235233Sbschmidt */ 1003235233Sbschmidtstatic uint16_t 1004235233Sbschmidtrt2860_eeprom_read_2(struct rt2860_softc *sc, uint16_t addr) 1005235233Sbschmidt{ 1006235233Sbschmidt uint32_t tmp; 1007235233Sbschmidt uint16_t val; 1008235233Sbschmidt int n; 1009235233Sbschmidt 1010235233Sbschmidt /* clock C once before the first command */ 1011235233Sbschmidt RT2860_EEPROM_CTL(sc, 0); 1012235233Sbschmidt 1013235233Sbschmidt RT2860_EEPROM_CTL(sc, RT2860_S); 1014235233Sbschmidt RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_C); 1015235233Sbschmidt RT2860_EEPROM_CTL(sc, RT2860_S); 1016235233Sbschmidt 1017235233Sbschmidt /* write start bit (1) */ 1018235233Sbschmidt RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_D); 1019235233Sbschmidt RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_D | RT2860_C); 1020235233Sbschmidt 1021235233Sbschmidt /* write READ opcode (10) */ 1022235233Sbschmidt RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_D); 1023235233Sbschmidt RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_D | RT2860_C); 1024235233Sbschmidt RT2860_EEPROM_CTL(sc, RT2860_S); 1025235233Sbschmidt RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_C); 1026235233Sbschmidt 1027235233Sbschmidt /* write address (A5-A0 or A7-A0) */ 1028235233Sbschmidt n = ((RAL_READ(sc, RT2860_PCI_EECTRL) & 0x30) == 0) ? 5 : 7; 1029235233Sbschmidt for (; n >= 0; n--) { 1030235233Sbschmidt RT2860_EEPROM_CTL(sc, RT2860_S | 1031235233Sbschmidt (((addr >> n) & 1) << RT2860_SHIFT_D)); 1032235233Sbschmidt RT2860_EEPROM_CTL(sc, RT2860_S | 1033235233Sbschmidt (((addr >> n) & 1) << RT2860_SHIFT_D) | RT2860_C); 1034235233Sbschmidt } 1035235233Sbschmidt 1036235233Sbschmidt RT2860_EEPROM_CTL(sc, RT2860_S); 1037235233Sbschmidt 1038235233Sbschmidt /* read data Q15-Q0 */ 1039235233Sbschmidt val = 0; 1040235233Sbschmidt for (n = 15; n >= 0; n--) { 1041235233Sbschmidt RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_C); 1042235233Sbschmidt tmp = RAL_READ(sc, RT2860_PCI_EECTRL); 1043235233Sbschmidt val |= ((tmp & RT2860_Q) >> RT2860_SHIFT_Q) << n; 1044235233Sbschmidt RT2860_EEPROM_CTL(sc, RT2860_S); 1045235233Sbschmidt } 1046235233Sbschmidt 1047235233Sbschmidt RT2860_EEPROM_CTL(sc, 0); 1048235233Sbschmidt 1049235233Sbschmidt /* clear Chip Select and clock C */ 1050235233Sbschmidt RT2860_EEPROM_CTL(sc, RT2860_S); 1051235233Sbschmidt RT2860_EEPROM_CTL(sc, 0); 1052235233Sbschmidt RT2860_EEPROM_CTL(sc, RT2860_C); 1053235233Sbschmidt 1054235233Sbschmidt return val; 1055235233Sbschmidt} 1056235233Sbschmidt 1057235233Sbschmidtstatic __inline uint16_t 1058235233Sbschmidtrt2860_srom_read(struct rt2860_softc *sc, uint8_t addr) 1059235233Sbschmidt{ 1060235233Sbschmidt /* either eFUSE ROM or EEPROM */ 1061235233Sbschmidt return sc->sc_srom_read(sc, addr); 1062235233Sbschmidt} 1063235233Sbschmidt 1064235233Sbschmidtstatic void 1065235233Sbschmidtrt2860_intr_coherent(struct rt2860_softc *sc) 1066235233Sbschmidt{ 1067235233Sbschmidt uint32_t tmp; 1068235233Sbschmidt 1069235233Sbschmidt /* DMA finds data coherent event when checking the DDONE bit */ 1070235233Sbschmidt 1071235233Sbschmidt DPRINTF(("Tx/Rx Coherent interrupt\n")); 1072235233Sbschmidt 1073235233Sbschmidt /* restart DMA engine */ 1074235233Sbschmidt tmp = RAL_READ(sc, RT2860_WPDMA_GLO_CFG); 1075235233Sbschmidt tmp &= ~(RT2860_TX_WB_DDONE | RT2860_RX_DMA_EN | RT2860_TX_DMA_EN); 1076235233Sbschmidt RAL_WRITE(sc, RT2860_WPDMA_GLO_CFG, tmp); 1077235233Sbschmidt 1078235233Sbschmidt (void)rt2860_txrx_enable(sc); 1079235233Sbschmidt} 1080235233Sbschmidt 1081235233Sbschmidtstatic void 1082235233Sbschmidtrt2860_drain_stats_fifo(struct rt2860_softc *sc) 1083235233Sbschmidt{ 1084235233Sbschmidt struct ieee80211_node *ni; 1085235233Sbschmidt uint32_t stat; 1086235233Sbschmidt int retrycnt; 1087235233Sbschmidt uint8_t wcid, mcs, pid; 1088235233Sbschmidt 1089235233Sbschmidt /* drain Tx status FIFO (maxsize = 16) */ 1090235233Sbschmidt while ((stat = RAL_READ(sc, RT2860_TX_STAT_FIFO)) & RT2860_TXQ_VLD) { 1091235233Sbschmidt DPRINTFN(4, ("tx stat 0x%08x\n", stat)); 1092235233Sbschmidt 1093235233Sbschmidt wcid = (stat >> RT2860_TXQ_WCID_SHIFT) & 0xff; 1094351143Skevans if (wcid > RT2860_WCID_MAX) 1095351143Skevans continue; 1096235233Sbschmidt ni = sc->wcid2ni[wcid]; 1097235233Sbschmidt 1098235233Sbschmidt /* if no ACK was requested, no feedback is available */ 1099351143Skevans if (!(stat & RT2860_TXQ_ACKREQ) || ni == NULL) 1100235233Sbschmidt continue; 1101235233Sbschmidt 1102235233Sbschmidt /* update per-STA AMRR stats */ 1103235233Sbschmidt if (stat & RT2860_TXQ_OK) { 1104235233Sbschmidt /* 1105235233Sbschmidt * Check if there were retries, ie if the Tx success 1106235233Sbschmidt * rate is different from the requested rate. Note 1107235233Sbschmidt * that it works only because we do not allow rate 1108235233Sbschmidt * fallback from OFDM to CCK. 1109235233Sbschmidt */ 1110235233Sbschmidt mcs = (stat >> RT2860_TXQ_MCS_SHIFT) & 0x7f; 1111235233Sbschmidt pid = (stat >> RT2860_TXQ_PID_SHIFT) & 0xf; 1112235233Sbschmidt if (mcs + 1 != pid) 1113235233Sbschmidt retrycnt = 1; 1114235233Sbschmidt else 1115235233Sbschmidt retrycnt = 0; 1116235233Sbschmidt ieee80211_ratectl_tx_complete(ni->ni_vap, ni, 1117235233Sbschmidt IEEE80211_RATECTL_TX_SUCCESS, &retrycnt, NULL); 1118235233Sbschmidt } else { 1119235233Sbschmidt ieee80211_ratectl_tx_complete(ni->ni_vap, ni, 1120235233Sbschmidt IEEE80211_RATECTL_TX_FAILURE, &retrycnt, NULL); 1121287197Sglebius if_inc_counter(ni->ni_vap->iv_ifp, 1122287197Sglebius IFCOUNTER_OERRORS, 1); 1123235233Sbschmidt } 1124235233Sbschmidt } 1125235233Sbschmidt} 1126235233Sbschmidt 1127235233Sbschmidtstatic void 1128235233Sbschmidtrt2860_tx_intr(struct rt2860_softc *sc, int qid) 1129235233Sbschmidt{ 1130235233Sbschmidt struct rt2860_tx_ring *ring = &sc->txq[qid]; 1131235233Sbschmidt uint32_t hw; 1132235233Sbschmidt 1133235233Sbschmidt rt2860_drain_stats_fifo(sc); 1134235233Sbschmidt 1135235233Sbschmidt hw = RAL_READ(sc, RT2860_TX_DTX_IDX(qid)); 1136235233Sbschmidt while (ring->next != hw) { 1137235233Sbschmidt struct rt2860_tx_data *data = ring->data[ring->next]; 1138235233Sbschmidt 1139235233Sbschmidt if (data != NULL) { 1140235233Sbschmidt bus_dmamap_sync(sc->txwi_dmat, data->map, 1141235233Sbschmidt BUS_DMASYNC_POSTWRITE); 1142235233Sbschmidt bus_dmamap_unload(sc->txwi_dmat, data->map); 1143287197Sglebius ieee80211_tx_complete(data->ni, data->m, 0); 1144287197Sglebius data->ni = NULL; 1145286437Sadrian data->m = NULL; 1146235233Sbschmidt SLIST_INSERT_HEAD(&sc->data_pool, data, next); 1147235233Sbschmidt ring->data[ring->next] = NULL; 1148235233Sbschmidt } 1149235233Sbschmidt ring->queued--; 1150235233Sbschmidt ring->next = (ring->next + 1) % RT2860_TX_RING_COUNT; 1151235233Sbschmidt } 1152235233Sbschmidt 1153235233Sbschmidt sc->sc_tx_timer = 0; 1154235233Sbschmidt if (ring->queued < RT2860_TX_RING_COUNT) 1155235233Sbschmidt sc->qfullmsk &= ~(1 << qid); 1156287197Sglebius rt2860_start(sc); 1157235233Sbschmidt} 1158235233Sbschmidt 1159235233Sbschmidt/* 1160235233Sbschmidt * Return the Rx chain with the highest RSSI for a given frame. 1161235233Sbschmidt */ 1162235233Sbschmidtstatic __inline uint8_t 1163235233Sbschmidtrt2860_maxrssi_chain(struct rt2860_softc *sc, const struct rt2860_rxwi *rxwi) 1164235233Sbschmidt{ 1165235233Sbschmidt uint8_t rxchain = 0; 1166235233Sbschmidt 1167235233Sbschmidt if (sc->nrxchains > 1) { 1168235233Sbschmidt if (rxwi->rssi[1] > rxwi->rssi[rxchain]) 1169235233Sbschmidt rxchain = 1; 1170235233Sbschmidt if (sc->nrxchains > 2) 1171235233Sbschmidt if (rxwi->rssi[2] > rxwi->rssi[rxchain]) 1172235233Sbschmidt rxchain = 2; 1173235233Sbschmidt } 1174235233Sbschmidt return rxchain; 1175235233Sbschmidt} 1176235233Sbschmidt 1177235233Sbschmidtstatic void 1178235233Sbschmidtrt2860_rx_intr(struct rt2860_softc *sc) 1179235233Sbschmidt{ 1180235233Sbschmidt struct rt2860_rx_radiotap_header *tap; 1181287197Sglebius struct ieee80211com *ic = &sc->sc_ic; 1182235233Sbschmidt struct ieee80211_frame *wh; 1183235233Sbschmidt struct ieee80211_node *ni; 1184235233Sbschmidt struct mbuf *m, *m1; 1185235233Sbschmidt bus_addr_t physaddr; 1186235233Sbschmidt uint32_t hw; 1187235233Sbschmidt uint16_t phy; 1188235233Sbschmidt uint8_t ant; 1189235233Sbschmidt int8_t rssi, nf; 1190235233Sbschmidt int error; 1191235233Sbschmidt 1192235233Sbschmidt hw = RAL_READ(sc, RT2860_FS_DRX_IDX) & 0xfff; 1193235233Sbschmidt while (sc->rxq.cur != hw) { 1194235233Sbschmidt struct rt2860_rx_data *data = &sc->rxq.data[sc->rxq.cur]; 1195235233Sbschmidt struct rt2860_rxd *rxd = &sc->rxq.rxd[sc->rxq.cur]; 1196235233Sbschmidt struct rt2860_rxwi *rxwi; 1197235233Sbschmidt 1198235233Sbschmidt bus_dmamap_sync(sc->rxq.desc_dmat, sc->rxq.desc_map, 1199235233Sbschmidt BUS_DMASYNC_POSTREAD); 1200235233Sbschmidt 1201235233Sbschmidt if (__predict_false(!(rxd->sdl0 & htole16(RT2860_RX_DDONE)))) { 1202235233Sbschmidt DPRINTF(("RXD DDONE bit not set!\n")); 1203235233Sbschmidt break; /* should not happen */ 1204235233Sbschmidt } 1205235233Sbschmidt 1206235233Sbschmidt if (__predict_false(rxd->flags & 1207235233Sbschmidt htole32(RT2860_RX_CRCERR | RT2860_RX_ICVERR))) { 1208287197Sglebius counter_u64_add(ic->ic_ierrors, 1); 1209235233Sbschmidt goto skip; 1210235233Sbschmidt } 1211235233Sbschmidt 1212235233Sbschmidt#ifdef HW_CRYPTO 1213235233Sbschmidt if (__predict_false(rxd->flags & htole32(RT2860_RX_MICERR))) { 1214235233Sbschmidt /* report MIC failures to net80211 for TKIP */ 1215235233Sbschmidt ic->ic_stats.is_rx_locmicfail++; 1216235233Sbschmidt ieee80211_michael_mic_failure(ic, 0/* XXX */); 1217287197Sglebius counter_u64_add(ic->ic_ierrors, 1); 1218235233Sbschmidt goto skip; 1219235233Sbschmidt } 1220235233Sbschmidt#endif 1221235233Sbschmidt 1222243857Sglebius m1 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 1223235233Sbschmidt if (__predict_false(m1 == NULL)) { 1224287197Sglebius counter_u64_add(ic->ic_ierrors, 1); 1225235233Sbschmidt goto skip; 1226235233Sbschmidt } 1227235233Sbschmidt 1228235233Sbschmidt bus_dmamap_sync(sc->rxq.data_dmat, data->map, 1229235233Sbschmidt BUS_DMASYNC_POSTREAD); 1230235233Sbschmidt bus_dmamap_unload(sc->rxq.data_dmat, data->map); 1231235233Sbschmidt 1232235233Sbschmidt error = bus_dmamap_load(sc->rxq.data_dmat, data->map, 1233235233Sbschmidt mtod(m1, void *), MCLBYTES, rt2860_dma_map_addr, 1234235233Sbschmidt &physaddr, 0); 1235235233Sbschmidt if (__predict_false(error != 0)) { 1236235233Sbschmidt m_freem(m1); 1237235233Sbschmidt 1238235233Sbschmidt /* try to reload the old mbuf */ 1239235233Sbschmidt error = bus_dmamap_load(sc->rxq.data_dmat, data->map, 1240235233Sbschmidt mtod(data->m, void *), MCLBYTES, 1241235233Sbschmidt rt2860_dma_map_addr, &physaddr, 0); 1242235233Sbschmidt if (__predict_false(error != 0)) { 1243235233Sbschmidt panic("%s: could not load old rx mbuf", 1244235233Sbschmidt device_get_name(sc->sc_dev)); 1245235233Sbschmidt } 1246235233Sbschmidt /* physical address may have changed */ 1247235233Sbschmidt rxd->sdp0 = htole32(physaddr); 1248287197Sglebius counter_u64_add(ic->ic_ierrors, 1); 1249235233Sbschmidt goto skip; 1250235233Sbschmidt } 1251235233Sbschmidt 1252235233Sbschmidt /* 1253235233Sbschmidt * New mbuf successfully loaded, update Rx ring and continue 1254235233Sbschmidt * processing. 1255235233Sbschmidt */ 1256235233Sbschmidt m = data->m; 1257235233Sbschmidt data->m = m1; 1258235233Sbschmidt rxd->sdp0 = htole32(physaddr); 1259235233Sbschmidt 1260235233Sbschmidt rxwi = mtod(m, struct rt2860_rxwi *); 1261235233Sbschmidt 1262235233Sbschmidt /* finalize mbuf */ 1263235233Sbschmidt m->m_data = (caddr_t)(rxwi + 1); 1264235233Sbschmidt m->m_pkthdr.len = m->m_len = le16toh(rxwi->len) & 0xfff; 1265235233Sbschmidt 1266235233Sbschmidt wh = mtod(m, struct ieee80211_frame *); 1267235233Sbschmidt#ifdef HW_CRYPTO 1268260444Skevlo if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { 1269235233Sbschmidt /* frame is decrypted by hardware */ 1270260444Skevlo wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED; 1271235233Sbschmidt } 1272235233Sbschmidt#endif 1273235233Sbschmidt 1274235233Sbschmidt /* HW may insert 2 padding bytes after 802.11 header */ 1275235233Sbschmidt if (rxd->flags & htole32(RT2860_RX_L2PAD)) { 1276235233Sbschmidt u_int hdrlen = ieee80211_hdrsize(wh); 1277235233Sbschmidt ovbcopy(wh, (caddr_t)wh + 2, hdrlen); 1278235233Sbschmidt m->m_data += 2; 1279235233Sbschmidt wh = mtod(m, struct ieee80211_frame *); 1280235233Sbschmidt } 1281235233Sbschmidt 1282235233Sbschmidt ant = rt2860_maxrssi_chain(sc, rxwi); 1283235233Sbschmidt rssi = rt2860_rssi2dbm(sc, rxwi->rssi[ant], ant); 1284235233Sbschmidt nf = RT2860_NOISE_FLOOR; 1285235233Sbschmidt 1286235233Sbschmidt if (ieee80211_radiotap_active(ic)) { 1287235233Sbschmidt tap = &sc->sc_rxtap; 1288235233Sbschmidt tap->wr_flags = 0; 1289235233Sbschmidt tap->wr_antenna = ant; 1290235233Sbschmidt tap->wr_antsignal = nf + rssi; 1291235233Sbschmidt tap->wr_antnoise = nf; 1292235233Sbschmidt /* in case it can't be found below */ 1293235233Sbschmidt tap->wr_rate = 2; 1294235233Sbschmidt phy = le16toh(rxwi->phy); 1295235233Sbschmidt switch (phy & RT2860_PHY_MODE) { 1296235233Sbschmidt case RT2860_PHY_CCK: 1297235233Sbschmidt switch ((phy & RT2860_PHY_MCS) & ~RT2860_PHY_SHPRE) { 1298235233Sbschmidt case 0: tap->wr_rate = 2; break; 1299235233Sbschmidt case 1: tap->wr_rate = 4; break; 1300235233Sbschmidt case 2: tap->wr_rate = 11; break; 1301235233Sbschmidt case 3: tap->wr_rate = 22; break; 1302235233Sbschmidt } 1303235233Sbschmidt if (phy & RT2860_PHY_SHPRE) 1304235233Sbschmidt tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; 1305235233Sbschmidt break; 1306235233Sbschmidt case RT2860_PHY_OFDM: 1307235233Sbschmidt switch (phy & RT2860_PHY_MCS) { 1308235233Sbschmidt case 0: tap->wr_rate = 12; break; 1309235233Sbschmidt case 1: tap->wr_rate = 18; break; 1310235233Sbschmidt case 2: tap->wr_rate = 24; break; 1311235233Sbschmidt case 3: tap->wr_rate = 36; break; 1312235233Sbschmidt case 4: tap->wr_rate = 48; break; 1313235233Sbschmidt case 5: tap->wr_rate = 72; break; 1314235233Sbschmidt case 6: tap->wr_rate = 96; break; 1315235233Sbschmidt case 7: tap->wr_rate = 108; break; 1316235233Sbschmidt } 1317235233Sbschmidt break; 1318235233Sbschmidt } 1319235233Sbschmidt } 1320235233Sbschmidt 1321235233Sbschmidt RAL_UNLOCK(sc); 1322235233Sbschmidt wh = mtod(m, struct ieee80211_frame *); 1323235233Sbschmidt 1324235233Sbschmidt /* send the frame to the 802.11 layer */ 1325235233Sbschmidt ni = ieee80211_find_rxnode(ic, 1326235233Sbschmidt (struct ieee80211_frame_min *)wh); 1327235233Sbschmidt if (ni != NULL) { 1328235233Sbschmidt (void)ieee80211_input(ni, m, rssi - nf, nf); 1329235233Sbschmidt ieee80211_free_node(ni); 1330235233Sbschmidt } else 1331235233Sbschmidt (void)ieee80211_input_all(ic, m, rssi - nf, nf); 1332235233Sbschmidt 1333235233Sbschmidt RAL_LOCK(sc); 1334235233Sbschmidt 1335235233Sbschmidtskip: rxd->sdl0 &= ~htole16(RT2860_RX_DDONE); 1336235233Sbschmidt 1337235233Sbschmidt bus_dmamap_sync(sc->rxq.desc_dmat, sc->rxq.desc_map, 1338235233Sbschmidt BUS_DMASYNC_PREWRITE); 1339235233Sbschmidt 1340235233Sbschmidt sc->rxq.cur = (sc->rxq.cur + 1) % RT2860_RX_RING_COUNT; 1341235233Sbschmidt } 1342235233Sbschmidt 1343235233Sbschmidt /* tell HW what we have processed */ 1344235233Sbschmidt RAL_WRITE(sc, RT2860_RX_CALC_IDX, 1345235233Sbschmidt (sc->rxq.cur - 1) % RT2860_RX_RING_COUNT); 1346235233Sbschmidt} 1347235233Sbschmidt 1348235233Sbschmidtstatic void 1349235233Sbschmidtrt2860_tbtt_intr(struct rt2860_softc *sc) 1350235233Sbschmidt{ 1351235233Sbschmidt#if 0 1352235233Sbschmidt struct ieee80211com *ic = &sc->sc_ic; 1353235233Sbschmidt 1354235233Sbschmidt#ifndef IEEE80211_STA_ONLY 1355235233Sbschmidt if (ic->ic_opmode == IEEE80211_M_HOSTAP) { 1356235233Sbschmidt /* one less beacon until next DTIM */ 1357235233Sbschmidt if (ic->ic_dtim_count == 0) 1358235233Sbschmidt ic->ic_dtim_count = ic->ic_dtim_period - 1; 1359235233Sbschmidt else 1360235233Sbschmidt ic->ic_dtim_count--; 1361235233Sbschmidt 1362235233Sbschmidt /* update dynamic parts of beacon */ 1363235233Sbschmidt rt2860_setup_beacon(sc); 1364235233Sbschmidt 1365235233Sbschmidt /* flush buffered multicast frames */ 1366235233Sbschmidt if (ic->ic_dtim_count == 0) 1367235233Sbschmidt ieee80211_notify_dtim(ic); 1368235233Sbschmidt } 1369235233Sbschmidt#endif 1370235233Sbschmidt /* check if protection mode has changed */ 1371235233Sbschmidt if ((sc->sc_ic_flags ^ ic->ic_flags) & IEEE80211_F_USEPROT) { 1372287197Sglebius rt2860_updateprot(sc); 1373235233Sbschmidt sc->sc_ic_flags = ic->ic_flags; 1374235233Sbschmidt } 1375235233Sbschmidt#endif 1376235233Sbschmidt} 1377235233Sbschmidt 1378235233Sbschmidtstatic void 1379235233Sbschmidtrt2860_gp_intr(struct rt2860_softc *sc) 1380235233Sbschmidt{ 1381287197Sglebius struct ieee80211com *ic = &sc->sc_ic; 1382235233Sbschmidt struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); 1383235233Sbschmidt 1384235233Sbschmidt DPRINTFN(2, ("GP timeout state=%d\n", vap->iv_state)); 1385235233Sbschmidt 1386235233Sbschmidt if (vap->iv_state == IEEE80211_S_RUN) 1387235233Sbschmidt rt2860_updatestats(sc); 1388235233Sbschmidt} 1389235233Sbschmidt 1390290134Skevlovoid 1391235233Sbschmidtrt2860_intr(void *arg) 1392235233Sbschmidt{ 1393235233Sbschmidt struct rt2860_softc *sc = arg; 1394235233Sbschmidt uint32_t r; 1395235233Sbschmidt 1396235233Sbschmidt RAL_LOCK(sc); 1397235233Sbschmidt 1398235233Sbschmidt r = RAL_READ(sc, RT2860_INT_STATUS); 1399235233Sbschmidt if (__predict_false(r == 0xffffffff)) { 1400235233Sbschmidt RAL_UNLOCK(sc); 1401235233Sbschmidt return; /* device likely went away */ 1402235233Sbschmidt } 1403235233Sbschmidt if (r == 0) { 1404235233Sbschmidt RAL_UNLOCK(sc); 1405235233Sbschmidt return; /* not for us */ 1406235233Sbschmidt } 1407235233Sbschmidt 1408235233Sbschmidt /* acknowledge interrupts */ 1409235233Sbschmidt RAL_WRITE(sc, RT2860_INT_STATUS, r); 1410235233Sbschmidt 1411235233Sbschmidt if (r & RT2860_TX_RX_COHERENT) 1412235233Sbschmidt rt2860_intr_coherent(sc); 1413235233Sbschmidt 1414235233Sbschmidt if (r & RT2860_MAC_INT_2) /* TX status */ 1415235233Sbschmidt rt2860_drain_stats_fifo(sc); 1416235233Sbschmidt 1417235233Sbschmidt if (r & RT2860_TX_DONE_INT5) 1418235233Sbschmidt rt2860_tx_intr(sc, 5); 1419235233Sbschmidt 1420235233Sbschmidt if (r & RT2860_RX_DONE_INT) 1421235233Sbschmidt rt2860_rx_intr(sc); 1422235233Sbschmidt 1423235233Sbschmidt if (r & RT2860_TX_DONE_INT4) 1424235233Sbschmidt rt2860_tx_intr(sc, 4); 1425235233Sbschmidt 1426235233Sbschmidt if (r & RT2860_TX_DONE_INT3) 1427235233Sbschmidt rt2860_tx_intr(sc, 3); 1428235233Sbschmidt 1429235233Sbschmidt if (r & RT2860_TX_DONE_INT2) 1430235233Sbschmidt rt2860_tx_intr(sc, 2); 1431235233Sbschmidt 1432235233Sbschmidt if (r & RT2860_TX_DONE_INT1) 1433235233Sbschmidt rt2860_tx_intr(sc, 1); 1434235233Sbschmidt 1435235233Sbschmidt if (r & RT2860_TX_DONE_INT0) 1436235233Sbschmidt rt2860_tx_intr(sc, 0); 1437235233Sbschmidt 1438235233Sbschmidt if (r & RT2860_MAC_INT_0) /* TBTT */ 1439235233Sbschmidt rt2860_tbtt_intr(sc); 1440235233Sbschmidt 1441235233Sbschmidt if (r & RT2860_MAC_INT_3) /* Auto wakeup */ 1442235233Sbschmidt /* TBD wakeup */; 1443235233Sbschmidt 1444235233Sbschmidt if (r & RT2860_MAC_INT_4) /* GP timer */ 1445235233Sbschmidt rt2860_gp_intr(sc); 1446235233Sbschmidt 1447235233Sbschmidt RAL_UNLOCK(sc); 1448235233Sbschmidt} 1449235233Sbschmidt 1450235233Sbschmidtstatic int 1451235233Sbschmidtrt2860_tx(struct rt2860_softc *sc, struct mbuf *m, struct ieee80211_node *ni) 1452235233Sbschmidt{ 1453287197Sglebius struct ieee80211com *ic = &sc->sc_ic; 1454235233Sbschmidt struct ieee80211vap *vap = ni->ni_vap; 1455235233Sbschmidt struct rt2860_tx_ring *ring; 1456235233Sbschmidt struct rt2860_tx_data *data; 1457235233Sbschmidt struct rt2860_txd *txd; 1458235233Sbschmidt struct rt2860_txwi *txwi; 1459235233Sbschmidt struct ieee80211_frame *wh; 1460235233Sbschmidt const struct ieee80211_txparam *tp; 1461235233Sbschmidt struct ieee80211_key *k; 1462235233Sbschmidt struct mbuf *m1; 1463235233Sbschmidt bus_dma_segment_t segs[RT2860_MAX_SCATTER]; 1464235233Sbschmidt bus_dma_segment_t *seg; 1465235233Sbschmidt u_int hdrlen; 1466235233Sbschmidt uint16_t qos, dur; 1467235233Sbschmidt uint8_t type, qsel, mcs, pid, tid, qid; 1468235233Sbschmidt int i, nsegs, ntxds, pad, rate, ridx, error; 1469235233Sbschmidt 1470235233Sbschmidt /* the data pool contains at least one element, pick the first */ 1471235233Sbschmidt data = SLIST_FIRST(&sc->data_pool); 1472235233Sbschmidt 1473235233Sbschmidt wh = mtod(m, struct ieee80211_frame *); 1474235233Sbschmidt 1475260444Skevlo if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { 1476235233Sbschmidt k = ieee80211_crypto_encap(ni, m); 1477235233Sbschmidt if (k == NULL) { 1478235233Sbschmidt m_freem(m); 1479235233Sbschmidt return ENOBUFS; 1480235233Sbschmidt } 1481235233Sbschmidt 1482235233Sbschmidt /* packet header may have moved, reset our local pointer */ 1483235233Sbschmidt wh = mtod(m, struct ieee80211_frame *); 1484235233Sbschmidt } 1485235233Sbschmidt 1486235233Sbschmidt hdrlen = ieee80211_anyhdrsize(wh); 1487235233Sbschmidt type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; 1488235233Sbschmidt 1489235233Sbschmidt tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)]; 1490235233Sbschmidt if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { 1491235233Sbschmidt rate = tp->mcastrate; 1492235233Sbschmidt } else if (m->m_flags & M_EAPOL) { 1493235233Sbschmidt rate = tp->mgmtrate; 1494235233Sbschmidt } else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { 1495235233Sbschmidt rate = tp->ucastrate; 1496235233Sbschmidt } else { 1497235233Sbschmidt (void) ieee80211_ratectl_rate(ni, NULL, 0); 1498235233Sbschmidt rate = ni->ni_txrate; 1499235233Sbschmidt } 1500235233Sbschmidt rate &= IEEE80211_RATE_VAL; 1501235233Sbschmidt 1502235233Sbschmidt qid = M_WME_GETAC(m); 1503235233Sbschmidt if (IEEE80211_QOS_HAS_SEQ(wh)) { 1504235233Sbschmidt qos = ((const struct ieee80211_qosframe *)wh)->i_qos[0]; 1505235233Sbschmidt tid = qos & IEEE80211_QOS_TID; 1506235233Sbschmidt } else { 1507235233Sbschmidt qos = 0; 1508235233Sbschmidt tid = 0; 1509235233Sbschmidt } 1510235233Sbschmidt ring = &sc->txq[qid]; 1511252727Sadrian ridx = ieee80211_legacy_rate_lookup(ic->ic_rt, rate); 1512235233Sbschmidt 1513235233Sbschmidt /* get MCS code from rate index */ 1514235233Sbschmidt mcs = rt2860_rates[ridx].mcs; 1515235233Sbschmidt 1516235233Sbschmidt /* setup TX Wireless Information */ 1517235233Sbschmidt txwi = data->txwi; 1518235233Sbschmidt txwi->flags = 0; 1519235233Sbschmidt /* let HW generate seq numbers for non-QoS frames */ 1520235233Sbschmidt txwi->xflags = qos ? 0 : RT2860_TX_NSEQ; 1521235233Sbschmidt if (type == IEEE80211_FC0_TYPE_DATA) 1522235233Sbschmidt txwi->wcid = IEEE80211_AID(ni->ni_associd); 1523235233Sbschmidt else 1524235233Sbschmidt txwi->wcid = 0xff; 1525235233Sbschmidt txwi->len = htole16(m->m_pkthdr.len); 1526235233Sbschmidt if (rt2860_rates[ridx].phy == IEEE80211_T_DS) { 1527235233Sbschmidt txwi->phy = htole16(RT2860_PHY_CCK); 1528235233Sbschmidt if (ridx != RT2860_RIDX_CCK1 && 1529235233Sbschmidt (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) 1530235233Sbschmidt mcs |= RT2860_PHY_SHPRE; 1531235233Sbschmidt } else 1532235233Sbschmidt txwi->phy = htole16(RT2860_PHY_OFDM); 1533235233Sbschmidt txwi->phy |= htole16(mcs); 1534235233Sbschmidt 1535235233Sbschmidt /* 1536235233Sbschmidt * We store the MCS code into the driver-private PacketID field. 1537235233Sbschmidt * The PacketID is latched into TX_STAT_FIFO when Tx completes so 1538235233Sbschmidt * that we know at which initial rate the frame was transmitted. 1539235233Sbschmidt * We add 1 to the MCS code because setting the PacketID field to 1540235233Sbschmidt * 0 means that we don't want feedback in TX_STAT_FIFO. 1541235233Sbschmidt */ 1542235233Sbschmidt pid = (mcs + 1) & 0xf; 1543235233Sbschmidt txwi->len |= htole16(pid << RT2860_TX_PID_SHIFT); 1544235233Sbschmidt 1545235233Sbschmidt /* check if RTS/CTS or CTS-to-self protection is required */ 1546235233Sbschmidt if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && 1547235233Sbschmidt (m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold || 1548235233Sbschmidt ((ic->ic_flags & IEEE80211_F_USEPROT) && 1549235233Sbschmidt rt2860_rates[ridx].phy == IEEE80211_T_OFDM))) 1550235233Sbschmidt txwi->txop = RT2860_TX_TXOP_HT; 1551235233Sbschmidt else 1552235233Sbschmidt txwi->txop = RT2860_TX_TXOP_BACKOFF; 1553235233Sbschmidt 1554235233Sbschmidt if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && 1555235233Sbschmidt (!qos || (qos & IEEE80211_QOS_ACKPOLICY) != 1556235233Sbschmidt IEEE80211_QOS_ACKPOLICY_NOACK)) { 1557235233Sbschmidt txwi->xflags |= RT2860_TX_ACK; 1558235233Sbschmidt 1559235233Sbschmidt if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) 1560235233Sbschmidt dur = rt2860_rates[ridx].sp_ack_dur; 1561235233Sbschmidt else 1562235233Sbschmidt dur = rt2860_rates[ridx].lp_ack_dur; 1563235233Sbschmidt *(uint16_t *)wh->i_dur = htole16(dur); 1564235233Sbschmidt } 1565235233Sbschmidt /* ask MAC to insert timestamp into probe responses */ 1566235233Sbschmidt if ((wh->i_fc[0] & 1567235233Sbschmidt (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == 1568235233Sbschmidt (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP)) 1569235233Sbschmidt /* NOTE: beacons do not pass through tx_data() */ 1570235233Sbschmidt txwi->flags |= RT2860_TX_TS; 1571235233Sbschmidt 1572235233Sbschmidt if (ieee80211_radiotap_active_vap(vap)) { 1573235233Sbschmidt struct rt2860_tx_radiotap_header *tap = &sc->sc_txtap; 1574235233Sbschmidt 1575235233Sbschmidt tap->wt_flags = 0; 1576235233Sbschmidt tap->wt_rate = rate; 1577235233Sbschmidt if (mcs & RT2860_PHY_SHPRE) 1578235233Sbschmidt tap->wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; 1579235233Sbschmidt 1580235233Sbschmidt ieee80211_radiotap_tx(vap, m); 1581235233Sbschmidt } 1582235233Sbschmidt 1583235233Sbschmidt pad = (hdrlen + 3) & ~3; 1584235233Sbschmidt 1585235233Sbschmidt /* copy and trim 802.11 header */ 1586235233Sbschmidt memcpy(txwi + 1, wh, hdrlen); 1587235233Sbschmidt m_adj(m, hdrlen); 1588235233Sbschmidt 1589235233Sbschmidt error = bus_dmamap_load_mbuf_sg(sc->txwi_dmat, data->map, m, segs, 1590235233Sbschmidt &nsegs, 0); 1591235233Sbschmidt if (__predict_false(error != 0 && error != EFBIG)) { 1592235233Sbschmidt device_printf(sc->sc_dev, "can't map mbuf (error %d)\n", 1593235233Sbschmidt error); 1594235233Sbschmidt m_freem(m); 1595235233Sbschmidt return error; 1596235233Sbschmidt } 1597235233Sbschmidt if (__predict_true(error == 0)) { 1598235233Sbschmidt /* determine how many TXDs are required */ 1599235233Sbschmidt ntxds = 1 + (nsegs / 2); 1600235233Sbschmidt 1601235233Sbschmidt if (ring->queued + ntxds >= RT2860_TX_RING_COUNT) { 1602235233Sbschmidt /* not enough free TXDs, force mbuf defrag */ 1603235233Sbschmidt bus_dmamap_unload(sc->txwi_dmat, data->map); 1604235233Sbschmidt error = EFBIG; 1605235233Sbschmidt } 1606235233Sbschmidt } 1607235233Sbschmidt if (__predict_false(error != 0)) { 1608243857Sglebius m1 = m_defrag(m, M_NOWAIT); 1609235233Sbschmidt if (m1 == NULL) { 1610235233Sbschmidt device_printf(sc->sc_dev, 1611235233Sbschmidt "could not defragment mbuf\n"); 1612235233Sbschmidt m_freem(m); 1613235233Sbschmidt return ENOBUFS; 1614235233Sbschmidt } 1615235233Sbschmidt m = m1; 1616235233Sbschmidt 1617235233Sbschmidt error = bus_dmamap_load_mbuf_sg(sc->txwi_dmat, data->map, m, 1618235233Sbschmidt segs, &nsegs, 0); 1619235233Sbschmidt if (__predict_false(error != 0)) { 1620235233Sbschmidt device_printf(sc->sc_dev, "can't map mbuf (error %d)\n", 1621235233Sbschmidt error); 1622235233Sbschmidt m_freem(m); 1623235233Sbschmidt return error; 1624235233Sbschmidt } 1625235233Sbschmidt 1626235233Sbschmidt /* determine how many TXDs are now required */ 1627235233Sbschmidt ntxds = 1 + (nsegs / 2); 1628235233Sbschmidt 1629235233Sbschmidt if (ring->queued + ntxds >= RT2860_TX_RING_COUNT) { 1630235233Sbschmidt /* this is a hopeless case, drop the mbuf! */ 1631235233Sbschmidt bus_dmamap_unload(sc->txwi_dmat, data->map); 1632235233Sbschmidt m_freem(m); 1633235233Sbschmidt return ENOBUFS; 1634235233Sbschmidt } 1635235233Sbschmidt } 1636235233Sbschmidt 1637235233Sbschmidt qsel = (qid < WME_NUM_AC) ? RT2860_TX_QSEL_EDCA : RT2860_TX_QSEL_MGMT; 1638235233Sbschmidt 1639235233Sbschmidt /* first segment is TXWI + 802.11 header */ 1640235233Sbschmidt txd = &ring->txd[ring->cur]; 1641235233Sbschmidt txd->sdp0 = htole32(data->paddr); 1642235233Sbschmidt txd->sdl0 = htole16(sizeof (struct rt2860_txwi) + pad); 1643235233Sbschmidt txd->flags = qsel; 1644235233Sbschmidt 1645235233Sbschmidt /* setup payload segments */ 1646235233Sbschmidt seg = &segs[0]; 1647235233Sbschmidt for (i = nsegs; i >= 2; i -= 2) { 1648235233Sbschmidt txd->sdp1 = htole32(seg->ds_addr); 1649235233Sbschmidt txd->sdl1 = htole16(seg->ds_len); 1650235233Sbschmidt seg++; 1651235233Sbschmidt ring->cur = (ring->cur + 1) % RT2860_TX_RING_COUNT; 1652235233Sbschmidt /* grab a new Tx descriptor */ 1653235233Sbschmidt txd = &ring->txd[ring->cur]; 1654235233Sbschmidt txd->sdp0 = htole32(seg->ds_addr); 1655235233Sbschmidt txd->sdl0 = htole16(seg->ds_len); 1656235233Sbschmidt txd->flags = qsel; 1657235233Sbschmidt seg++; 1658235233Sbschmidt } 1659235233Sbschmidt /* finalize last segment */ 1660235233Sbschmidt if (i > 0) { 1661235233Sbschmidt txd->sdp1 = htole32(seg->ds_addr); 1662235233Sbschmidt txd->sdl1 = htole16(seg->ds_len | RT2860_TX_LS1); 1663235233Sbschmidt } else { 1664235233Sbschmidt txd->sdl0 |= htole16(RT2860_TX_LS0); 1665235233Sbschmidt txd->sdl1 = 0; 1666235233Sbschmidt } 1667235233Sbschmidt 1668235233Sbschmidt /* remove from the free pool and link it into the SW Tx slot */ 1669235233Sbschmidt SLIST_REMOVE_HEAD(&sc->data_pool, next); 1670235233Sbschmidt data->m = m; 1671235233Sbschmidt data->ni = ni; 1672235233Sbschmidt ring->data[ring->cur] = data; 1673235233Sbschmidt 1674235233Sbschmidt bus_dmamap_sync(sc->txwi_dmat, sc->txwi_map, BUS_DMASYNC_PREWRITE); 1675235233Sbschmidt bus_dmamap_sync(sc->txwi_dmat, data->map, BUS_DMASYNC_PREWRITE); 1676235233Sbschmidt bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_PREWRITE); 1677235233Sbschmidt 1678235233Sbschmidt DPRINTFN(4, ("sending frame qid=%d wcid=%d nsegs=%d ridx=%d\n", 1679235233Sbschmidt qid, txwi->wcid, nsegs, ridx)); 1680235233Sbschmidt 1681235233Sbschmidt ring->cur = (ring->cur + 1) % RT2860_TX_RING_COUNT; 1682235233Sbschmidt ring->queued += ntxds; 1683235233Sbschmidt if (ring->queued >= RT2860_TX_RING_COUNT) 1684235233Sbschmidt sc->qfullmsk |= 1 << qid; 1685235233Sbschmidt 1686235233Sbschmidt /* kick Tx */ 1687235233Sbschmidt RAL_WRITE(sc, RT2860_TX_CTX_IDX(qid), ring->cur); 1688235233Sbschmidt 1689235233Sbschmidt return 0; 1690235233Sbschmidt} 1691235233Sbschmidt 1692235233Sbschmidtstatic int 1693235233Sbschmidtrt2860_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, 1694235233Sbschmidt const struct ieee80211_bpf_params *params) 1695235233Sbschmidt{ 1696235233Sbschmidt struct ieee80211com *ic = ni->ni_ic; 1697287197Sglebius struct rt2860_softc *sc = ic->ic_softc; 1698235233Sbschmidt int error; 1699235233Sbschmidt 1700235233Sbschmidt RAL_LOCK(sc); 1701235233Sbschmidt 1702235233Sbschmidt /* prevent management frames from being sent if we're not ready */ 1703290133Skevlo if (!(sc->sc_flags & RT2860_RUNNING)) { 1704235233Sbschmidt RAL_UNLOCK(sc); 1705235233Sbschmidt m_freem(m); 1706235233Sbschmidt return ENETDOWN; 1707235233Sbschmidt } 1708235233Sbschmidt if (params == NULL) { 1709235233Sbschmidt /* 1710235233Sbschmidt * Legacy path; interpret frame contents to decide 1711235233Sbschmidt * precisely how to send the frame. 1712235233Sbschmidt */ 1713235233Sbschmidt error = rt2860_tx(sc, m, ni); 1714235233Sbschmidt } else { 1715235233Sbschmidt /* 1716235233Sbschmidt * Caller supplied explicit parameters to use in 1717235233Sbschmidt * sending the frame. 1718235233Sbschmidt */ 1719235233Sbschmidt error = rt2860_tx_raw(sc, m, ni, params); 1720235233Sbschmidt } 1721235233Sbschmidt sc->sc_tx_timer = 5; 1722235233Sbschmidt RAL_UNLOCK(sc); 1723235233Sbschmidt return error; 1724235233Sbschmidt} 1725235233Sbschmidt 1726235233Sbschmidtstatic int 1727235233Sbschmidtrt2860_tx_raw(struct rt2860_softc *sc, struct mbuf *m, 1728235233Sbschmidt struct ieee80211_node *ni, const struct ieee80211_bpf_params *params) 1729235233Sbschmidt{ 1730287197Sglebius struct ieee80211com *ic = &sc->sc_ic; 1731235233Sbschmidt struct ieee80211vap *vap = ni->ni_vap; 1732235233Sbschmidt struct rt2860_tx_ring *ring; 1733235233Sbschmidt struct rt2860_tx_data *data; 1734235233Sbschmidt struct rt2860_txd *txd; 1735235233Sbschmidt struct rt2860_txwi *txwi; 1736235233Sbschmidt struct ieee80211_frame *wh; 1737235233Sbschmidt struct mbuf *m1; 1738235233Sbschmidt bus_dma_segment_t segs[RT2860_MAX_SCATTER]; 1739235233Sbschmidt bus_dma_segment_t *seg; 1740235233Sbschmidt u_int hdrlen; 1741235233Sbschmidt uint16_t dur; 1742235233Sbschmidt uint8_t type, qsel, mcs, pid, tid, qid; 1743235233Sbschmidt int i, nsegs, ntxds, pad, rate, ridx, error; 1744235233Sbschmidt 1745235233Sbschmidt /* the data pool contains at least one element, pick the first */ 1746235233Sbschmidt data = SLIST_FIRST(&sc->data_pool); 1747235233Sbschmidt 1748235233Sbschmidt wh = mtod(m, struct ieee80211_frame *); 1749235233Sbschmidt hdrlen = ieee80211_hdrsize(wh); 1750235233Sbschmidt type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; 1751235233Sbschmidt 1752235233Sbschmidt /* Choose a TX rate index. */ 1753235233Sbschmidt rate = params->ibp_rate0; 1754252727Sadrian ridx = ieee80211_legacy_rate_lookup(ic->ic_rt, 1755252727Sadrian rate & IEEE80211_RATE_VAL); 1756235233Sbschmidt if (ridx == (uint8_t)-1) { 1757235233Sbschmidt /* XXX fall back to mcast/mgmt rate? */ 1758235233Sbschmidt m_freem(m); 1759235233Sbschmidt return EINVAL; 1760235233Sbschmidt } 1761235233Sbschmidt 1762235233Sbschmidt qid = params->ibp_pri & 3; 1763235233Sbschmidt tid = 0; 1764235233Sbschmidt ring = &sc->txq[qid]; 1765235233Sbschmidt 1766235233Sbschmidt /* get MCS code from rate index */ 1767235233Sbschmidt mcs = rt2860_rates[ridx].mcs; 1768235233Sbschmidt 1769235233Sbschmidt /* setup TX Wireless Information */ 1770235233Sbschmidt txwi = data->txwi; 1771235233Sbschmidt txwi->flags = 0; 1772235233Sbschmidt /* let HW generate seq numbers for non-QoS frames */ 1773235233Sbschmidt txwi->xflags = params->ibp_pri & 3 ? 0 : RT2860_TX_NSEQ; 1774235233Sbschmidt txwi->wcid = 0xff; 1775235233Sbschmidt txwi->len = htole16(m->m_pkthdr.len); 1776235233Sbschmidt if (rt2860_rates[ridx].phy == IEEE80211_T_DS) { 1777235233Sbschmidt txwi->phy = htole16(RT2860_PHY_CCK); 1778235233Sbschmidt if (ridx != RT2860_RIDX_CCK1 && 1779235233Sbschmidt (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) 1780235233Sbschmidt mcs |= RT2860_PHY_SHPRE; 1781235233Sbschmidt } else 1782235233Sbschmidt txwi->phy = htole16(RT2860_PHY_OFDM); 1783235233Sbschmidt txwi->phy |= htole16(mcs); 1784235233Sbschmidt 1785235233Sbschmidt /* 1786235233Sbschmidt * We store the MCS code into the driver-private PacketID field. 1787235233Sbschmidt * The PacketID is latched into TX_STAT_FIFO when Tx completes so 1788235233Sbschmidt * that we know at which initial rate the frame was transmitted. 1789235233Sbschmidt * We add 1 to the MCS code because setting the PacketID field to 1790235233Sbschmidt * 0 means that we don't want feedback in TX_STAT_FIFO. 1791235233Sbschmidt */ 1792235233Sbschmidt pid = (mcs + 1) & 0xf; 1793235233Sbschmidt txwi->len |= htole16(pid << RT2860_TX_PID_SHIFT); 1794235233Sbschmidt 1795235233Sbschmidt /* check if RTS/CTS or CTS-to-self protection is required */ 1796235233Sbschmidt if (params->ibp_flags & IEEE80211_BPF_RTS || 1797235233Sbschmidt params->ibp_flags & IEEE80211_BPF_CTS) 1798235233Sbschmidt txwi->txop = RT2860_TX_TXOP_HT; 1799235233Sbschmidt else 1800235233Sbschmidt txwi->txop = RT2860_TX_TXOP_BACKOFF; 1801235233Sbschmidt if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0) { 1802235233Sbschmidt txwi->xflags |= RT2860_TX_ACK; 1803235233Sbschmidt 1804235233Sbschmidt if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) 1805235233Sbschmidt dur = rt2860_rates[ridx].sp_ack_dur; 1806235233Sbschmidt else 1807235233Sbschmidt dur = rt2860_rates[ridx].lp_ack_dur; 1808235233Sbschmidt *(uint16_t *)wh->i_dur = htole16(dur); 1809235233Sbschmidt } 1810235233Sbschmidt /* ask MAC to insert timestamp into probe responses */ 1811235233Sbschmidt if ((wh->i_fc[0] & 1812235233Sbschmidt (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == 1813235233Sbschmidt (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP)) 1814235233Sbschmidt /* NOTE: beacons do not pass through tx_data() */ 1815235233Sbschmidt txwi->flags |= RT2860_TX_TS; 1816235233Sbschmidt 1817235233Sbschmidt if (ieee80211_radiotap_active_vap(vap)) { 1818235233Sbschmidt struct rt2860_tx_radiotap_header *tap = &sc->sc_txtap; 1819235233Sbschmidt 1820235233Sbschmidt tap->wt_flags = 0; 1821235233Sbschmidt tap->wt_rate = rate; 1822235233Sbschmidt if (mcs & RT2860_PHY_SHPRE) 1823235233Sbschmidt tap->wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; 1824235233Sbschmidt 1825235233Sbschmidt ieee80211_radiotap_tx(vap, m); 1826235233Sbschmidt } 1827235233Sbschmidt 1828235233Sbschmidt pad = (hdrlen + 3) & ~3; 1829235233Sbschmidt 1830235233Sbschmidt /* copy and trim 802.11 header */ 1831235233Sbschmidt memcpy(txwi + 1, wh, hdrlen); 1832235233Sbschmidt m_adj(m, hdrlen); 1833235233Sbschmidt 1834235233Sbschmidt error = bus_dmamap_load_mbuf_sg(sc->txwi_dmat, data->map, m, segs, 1835235233Sbschmidt &nsegs, 0); 1836235233Sbschmidt if (__predict_false(error != 0 && error != EFBIG)) { 1837235233Sbschmidt device_printf(sc->sc_dev, "can't map mbuf (error %d)\n", 1838235233Sbschmidt error); 1839235233Sbschmidt m_freem(m); 1840235233Sbschmidt return error; 1841235233Sbschmidt } 1842235233Sbschmidt if (__predict_true(error == 0)) { 1843235233Sbschmidt /* determine how many TXDs are required */ 1844235233Sbschmidt ntxds = 1 + (nsegs / 2); 1845235233Sbschmidt 1846235233Sbschmidt if (ring->queued + ntxds >= RT2860_TX_RING_COUNT) { 1847235233Sbschmidt /* not enough free TXDs, force mbuf defrag */ 1848235233Sbschmidt bus_dmamap_unload(sc->txwi_dmat, data->map); 1849235233Sbschmidt error = EFBIG; 1850235233Sbschmidt } 1851235233Sbschmidt } 1852235233Sbschmidt if (__predict_false(error != 0)) { 1853243857Sglebius m1 = m_defrag(m, M_NOWAIT); 1854235233Sbschmidt if (m1 == NULL) { 1855235233Sbschmidt device_printf(sc->sc_dev, 1856235233Sbschmidt "could not defragment mbuf\n"); 1857235233Sbschmidt m_freem(m); 1858235233Sbschmidt return ENOBUFS; 1859235233Sbschmidt } 1860235233Sbschmidt m = m1; 1861235233Sbschmidt 1862235233Sbschmidt error = bus_dmamap_load_mbuf_sg(sc->txwi_dmat, data->map, m, 1863235233Sbschmidt segs, &nsegs, 0); 1864235233Sbschmidt if (__predict_false(error != 0)) { 1865235233Sbschmidt device_printf(sc->sc_dev, "can't map mbuf (error %d)\n", 1866235233Sbschmidt error); 1867235233Sbschmidt m_freem(m); 1868235233Sbschmidt return error; 1869235233Sbschmidt } 1870235233Sbschmidt 1871235233Sbschmidt /* determine how many TXDs are now required */ 1872235233Sbschmidt ntxds = 1 + (nsegs / 2); 1873235233Sbschmidt 1874235233Sbschmidt if (ring->queued + ntxds >= RT2860_TX_RING_COUNT) { 1875235233Sbschmidt /* this is a hopeless case, drop the mbuf! */ 1876235233Sbschmidt bus_dmamap_unload(sc->txwi_dmat, data->map); 1877235233Sbschmidt m_freem(m); 1878235233Sbschmidt return ENOBUFS; 1879235233Sbschmidt } 1880235233Sbschmidt } 1881235233Sbschmidt 1882235233Sbschmidt qsel = (qid < WME_NUM_AC) ? RT2860_TX_QSEL_EDCA : RT2860_TX_QSEL_MGMT; 1883235233Sbschmidt 1884235233Sbschmidt /* first segment is TXWI + 802.11 header */ 1885235233Sbschmidt txd = &ring->txd[ring->cur]; 1886235233Sbschmidt txd->sdp0 = htole32(data->paddr); 1887235233Sbschmidt txd->sdl0 = htole16(sizeof (struct rt2860_txwi) + pad); 1888235233Sbschmidt txd->flags = qsel; 1889235233Sbschmidt 1890235233Sbschmidt /* setup payload segments */ 1891235233Sbschmidt seg = &segs[0]; 1892235233Sbschmidt for (i = nsegs; i >= 2; i -= 2) { 1893235233Sbschmidt txd->sdp1 = htole32(seg->ds_addr); 1894235233Sbschmidt txd->sdl1 = htole16(seg->ds_len); 1895235233Sbschmidt seg++; 1896235233Sbschmidt ring->cur = (ring->cur + 1) % RT2860_TX_RING_COUNT; 1897235233Sbschmidt /* grab a new Tx descriptor */ 1898235233Sbschmidt txd = &ring->txd[ring->cur]; 1899235233Sbschmidt txd->sdp0 = htole32(seg->ds_addr); 1900235233Sbschmidt txd->sdl0 = htole16(seg->ds_len); 1901235233Sbschmidt txd->flags = qsel; 1902235233Sbschmidt seg++; 1903235233Sbschmidt } 1904235233Sbschmidt /* finalize last segment */ 1905235233Sbschmidt if (i > 0) { 1906235233Sbschmidt txd->sdp1 = htole32(seg->ds_addr); 1907235233Sbschmidt txd->sdl1 = htole16(seg->ds_len | RT2860_TX_LS1); 1908235233Sbschmidt } else { 1909235233Sbschmidt txd->sdl0 |= htole16(RT2860_TX_LS0); 1910235233Sbschmidt txd->sdl1 = 0; 1911235233Sbschmidt } 1912235233Sbschmidt 1913235233Sbschmidt /* remove from the free pool and link it into the SW Tx slot */ 1914235233Sbschmidt SLIST_REMOVE_HEAD(&sc->data_pool, next); 1915235233Sbschmidt data->m = m; 1916235233Sbschmidt data->ni = ni; 1917235233Sbschmidt ring->data[ring->cur] = data; 1918235233Sbschmidt 1919235233Sbschmidt bus_dmamap_sync(sc->txwi_dmat, sc->txwi_map, BUS_DMASYNC_PREWRITE); 1920235233Sbschmidt bus_dmamap_sync(sc->txwi_dmat, data->map, BUS_DMASYNC_PREWRITE); 1921235233Sbschmidt bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_PREWRITE); 1922235233Sbschmidt 1923235233Sbschmidt DPRINTFN(4, ("sending frame qid=%d wcid=%d nsegs=%d ridx=%d\n", 1924235233Sbschmidt qid, txwi->wcid, nsegs, ridx)); 1925235233Sbschmidt 1926235233Sbschmidt ring->cur = (ring->cur + 1) % RT2860_TX_RING_COUNT; 1927235233Sbschmidt ring->queued += ntxds; 1928235233Sbschmidt if (ring->queued >= RT2860_TX_RING_COUNT) 1929235233Sbschmidt sc->qfullmsk |= 1 << qid; 1930235233Sbschmidt 1931235233Sbschmidt /* kick Tx */ 1932235233Sbschmidt RAL_WRITE(sc, RT2860_TX_CTX_IDX(qid), ring->cur); 1933235233Sbschmidt 1934235233Sbschmidt return 0; 1935235233Sbschmidt} 1936235233Sbschmidt 1937287197Sglebiusstatic int 1938287197Sglebiusrt2860_transmit(struct ieee80211com *ic, struct mbuf *m) 1939235233Sbschmidt{ 1940287197Sglebius struct rt2860_softc *sc = ic->ic_softc; 1941287197Sglebius int error; 1942235233Sbschmidt 1943235233Sbschmidt RAL_LOCK(sc); 1944290133Skevlo if ((sc->sc_flags & RT2860_RUNNING) == 0) { 1945287197Sglebius RAL_UNLOCK(sc); 1946287197Sglebius return (ENXIO); 1947287197Sglebius } 1948287197Sglebius error = mbufq_enqueue(&sc->sc_snd, m); 1949287197Sglebius if (error) { 1950287197Sglebius RAL_UNLOCK(sc); 1951287197Sglebius return (error); 1952287197Sglebius } 1953287197Sglebius rt2860_start(sc); 1954235233Sbschmidt RAL_UNLOCK(sc); 1955287197Sglebius 1956287197Sglebius return (0); 1957235233Sbschmidt} 1958235233Sbschmidt 1959235233Sbschmidtstatic void 1960287197Sglebiusrt2860_start(struct rt2860_softc *sc) 1961235233Sbschmidt{ 1962235233Sbschmidt struct ieee80211_node *ni; 1963235233Sbschmidt struct mbuf *m; 1964235233Sbschmidt 1965235233Sbschmidt RAL_LOCK_ASSERT(sc); 1966235233Sbschmidt 1967290133Skevlo if ((sc->sc_flags & RT2860_RUNNING) == 0) 1968235233Sbschmidt return; 1969235233Sbschmidt 1970287197Sglebius while (!SLIST_EMPTY(&sc->data_pool) && sc->qfullmsk == 0 && 1971287197Sglebius (m = mbufq_dequeue(&sc->sc_snd)) != NULL) { 1972235233Sbschmidt ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; 1973235233Sbschmidt if (rt2860_tx(sc, m, ni) != 0) { 1974287197Sglebius if_inc_counter(ni->ni_vap->iv_ifp, 1975287197Sglebius IFCOUNTER_OERRORS, 1); 1976235233Sbschmidt ieee80211_free_node(ni); 1977235233Sbschmidt continue; 1978235233Sbschmidt } 1979235233Sbschmidt sc->sc_tx_timer = 5; 1980235233Sbschmidt } 1981235233Sbschmidt} 1982235233Sbschmidt 1983235233Sbschmidtstatic void 1984235233Sbschmidtrt2860_watchdog(void *arg) 1985235233Sbschmidt{ 1986235233Sbschmidt struct rt2860_softc *sc = arg; 1987235233Sbschmidt 1988235233Sbschmidt RAL_LOCK_ASSERT(sc); 1989235233Sbschmidt 1990290133Skevlo KASSERT(sc->sc_flags & RT2860_RUNNING, ("not running")); 1991235233Sbschmidt 1992235233Sbschmidt if (sc->sc_invalid) /* card ejected */ 1993235233Sbschmidt return; 1994235233Sbschmidt 1995235233Sbschmidt if (sc->sc_tx_timer > 0 && --sc->sc_tx_timer == 0) { 1996287197Sglebius device_printf(sc->sc_dev, "device timeout\n"); 1997235233Sbschmidt rt2860_stop_locked(sc); 1998235233Sbschmidt rt2860_init_locked(sc); 1999287197Sglebius counter_u64_add(sc->sc_ic.ic_oerrors, 1); 2000235233Sbschmidt return; 2001235233Sbschmidt } 2002235233Sbschmidt callout_reset(&sc->watchdog_ch, hz, rt2860_watchdog, sc); 2003235233Sbschmidt} 2004235233Sbschmidt 2005287197Sglebiusstatic void 2006287197Sglebiusrt2860_parent(struct ieee80211com *ic) 2007235233Sbschmidt{ 2008287197Sglebius struct rt2860_softc *sc = ic->ic_softc; 2009287197Sglebius int startall = 0; 2010235233Sbschmidt 2011287197Sglebius RAL_LOCK(sc); 2012287197Sglebius if (ic->ic_nrunning> 0) { 2013290133Skevlo if (!(sc->sc_flags & RT2860_RUNNING)) { 2014287197Sglebius rt2860_init_locked(sc); 2015287197Sglebius startall = 1; 2016287197Sglebius } else 2017287197Sglebius rt2860_update_promisc(ic); 2018290133Skevlo } else if (sc->sc_flags & RT2860_RUNNING) 2019287197Sglebius rt2860_stop_locked(sc); 2020287197Sglebius RAL_UNLOCK(sc); 2021287197Sglebius if (startall) 2022287197Sglebius ieee80211_start_all(ic); 2023235233Sbschmidt} 2024235233Sbschmidt 2025235233Sbschmidt/* 2026235233Sbschmidt * Reading and writing from/to the BBP is different from RT2560 and RT2661. 2027235233Sbschmidt * We access the BBP through the 8051 microcontroller unit which means that 2028235233Sbschmidt * the microcode must be loaded first. 2029235233Sbschmidt */ 2030235233Sbschmidtvoid 2031235233Sbschmidtrt2860_mcu_bbp_write(struct rt2860_softc *sc, uint8_t reg, uint8_t val) 2032235233Sbschmidt{ 2033235233Sbschmidt int ntries; 2034235233Sbschmidt 2035235233Sbschmidt for (ntries = 0; ntries < 100; ntries++) { 2036235233Sbschmidt if (!(RAL_READ(sc, RT2860_H2M_BBPAGENT) & RT2860_BBP_CSR_KICK)) 2037235233Sbschmidt break; 2038235233Sbschmidt DELAY(1); 2039235233Sbschmidt } 2040235233Sbschmidt if (ntries == 100) { 2041235233Sbschmidt device_printf(sc->sc_dev, 2042278551Skevlo "could not write to BBP through MCU\n"); 2043235233Sbschmidt return; 2044235233Sbschmidt } 2045235233Sbschmidt 2046235233Sbschmidt RAL_WRITE(sc, RT2860_H2M_BBPAGENT, RT2860_BBP_RW_PARALLEL | 2047235233Sbschmidt RT2860_BBP_CSR_KICK | reg << 8 | val); 2048235233Sbschmidt RAL_BARRIER_WRITE(sc); 2049235233Sbschmidt 2050235233Sbschmidt rt2860_mcu_cmd(sc, RT2860_MCU_CMD_BBP, 0, 0); 2051235233Sbschmidt DELAY(1000); 2052235233Sbschmidt} 2053235233Sbschmidt 2054235233Sbschmidtuint8_t 2055235233Sbschmidtrt2860_mcu_bbp_read(struct rt2860_softc *sc, uint8_t reg) 2056235233Sbschmidt{ 2057235233Sbschmidt uint32_t val; 2058235233Sbschmidt int ntries; 2059235233Sbschmidt 2060235233Sbschmidt for (ntries = 0; ntries < 100; ntries++) { 2061235233Sbschmidt if (!(RAL_READ(sc, RT2860_H2M_BBPAGENT) & RT2860_BBP_CSR_KICK)) 2062235233Sbschmidt break; 2063235233Sbschmidt DELAY(1); 2064235233Sbschmidt } 2065235233Sbschmidt if (ntries == 100) { 2066235233Sbschmidt device_printf(sc->sc_dev, 2067235233Sbschmidt "could not read from BBP through MCU\n"); 2068235233Sbschmidt return 0; 2069235233Sbschmidt } 2070235233Sbschmidt 2071235233Sbschmidt RAL_WRITE(sc, RT2860_H2M_BBPAGENT, RT2860_BBP_RW_PARALLEL | 2072235233Sbschmidt RT2860_BBP_CSR_KICK | RT2860_BBP_CSR_READ | reg << 8); 2073235233Sbschmidt RAL_BARRIER_WRITE(sc); 2074235233Sbschmidt 2075235233Sbschmidt rt2860_mcu_cmd(sc, RT2860_MCU_CMD_BBP, 0, 0); 2076235233Sbschmidt DELAY(1000); 2077235233Sbschmidt 2078235233Sbschmidt for (ntries = 0; ntries < 100; ntries++) { 2079235233Sbschmidt val = RAL_READ(sc, RT2860_H2M_BBPAGENT); 2080235233Sbschmidt if (!(val & RT2860_BBP_CSR_KICK)) 2081235233Sbschmidt return val & 0xff; 2082235233Sbschmidt DELAY(1); 2083235233Sbschmidt } 2084235233Sbschmidt device_printf(sc->sc_dev, "could not read from BBP through MCU\n"); 2085235233Sbschmidt 2086235233Sbschmidt return 0; 2087235233Sbschmidt} 2088235233Sbschmidt 2089235233Sbschmidt/* 2090235233Sbschmidt * Write to one of the 4 programmable 24-bit RF registers. 2091235233Sbschmidt */ 2092235233Sbschmidtstatic void 2093235233Sbschmidtrt2860_rf_write(struct rt2860_softc *sc, uint8_t reg, uint32_t val) 2094235233Sbschmidt{ 2095235233Sbschmidt uint32_t tmp; 2096235233Sbschmidt int ntries; 2097235233Sbschmidt 2098235233Sbschmidt for (ntries = 0; ntries < 100; ntries++) { 2099235233Sbschmidt if (!(RAL_READ(sc, RT2860_RF_CSR_CFG0) & RT2860_RF_REG_CTRL)) 2100235233Sbschmidt break; 2101235233Sbschmidt DELAY(1); 2102235233Sbschmidt } 2103235233Sbschmidt if (ntries == 100) { 2104235233Sbschmidt device_printf(sc->sc_dev, "could not write to RF\n"); 2105235233Sbschmidt return; 2106235233Sbschmidt } 2107235233Sbschmidt 2108235233Sbschmidt /* RF registers are 24-bit on the RT2860 */ 2109235233Sbschmidt tmp = RT2860_RF_REG_CTRL | 24 << RT2860_RF_REG_WIDTH_SHIFT | 2110235233Sbschmidt (val & 0x3fffff) << 2 | (reg & 3); 2111235233Sbschmidt RAL_WRITE(sc, RT2860_RF_CSR_CFG0, tmp); 2112235233Sbschmidt} 2113235233Sbschmidt 2114235233Sbschmidtstatic uint8_t 2115235233Sbschmidtrt3090_rf_read(struct rt2860_softc *sc, uint8_t reg) 2116235233Sbschmidt{ 2117235233Sbschmidt uint32_t tmp; 2118235233Sbschmidt int ntries; 2119235233Sbschmidt 2120235233Sbschmidt for (ntries = 0; ntries < 100; ntries++) { 2121235233Sbschmidt if (!(RAL_READ(sc, RT3070_RF_CSR_CFG) & RT3070_RF_KICK)) 2122235233Sbschmidt break; 2123235233Sbschmidt DELAY(1); 2124235233Sbschmidt } 2125235233Sbschmidt if (ntries == 100) { 2126235233Sbschmidt device_printf(sc->sc_dev, "could not read RF register\n"); 2127235233Sbschmidt return 0xff; 2128235233Sbschmidt } 2129235233Sbschmidt tmp = RT3070_RF_KICK | reg << 8; 2130235233Sbschmidt RAL_WRITE(sc, RT3070_RF_CSR_CFG, tmp); 2131235233Sbschmidt 2132235233Sbschmidt for (ntries = 0; ntries < 100; ntries++) { 2133235233Sbschmidt tmp = RAL_READ(sc, RT3070_RF_CSR_CFG); 2134235233Sbschmidt if (!(tmp & RT3070_RF_KICK)) 2135235233Sbschmidt break; 2136235233Sbschmidt DELAY(1); 2137235233Sbschmidt } 2138235233Sbschmidt if (ntries == 100) { 2139235233Sbschmidt device_printf(sc->sc_dev, "could not read RF register\n"); 2140235233Sbschmidt return 0xff; 2141235233Sbschmidt } 2142235233Sbschmidt return tmp & 0xff; 2143235233Sbschmidt} 2144235233Sbschmidt 2145235233Sbschmidtvoid 2146235233Sbschmidtrt3090_rf_write(struct rt2860_softc *sc, uint8_t reg, uint8_t val) 2147235233Sbschmidt{ 2148235233Sbschmidt uint32_t tmp; 2149235233Sbschmidt int ntries; 2150235233Sbschmidt 2151235233Sbschmidt for (ntries = 0; ntries < 10; ntries++) { 2152235233Sbschmidt if (!(RAL_READ(sc, RT3070_RF_CSR_CFG) & RT3070_RF_KICK)) 2153235233Sbschmidt break; 2154235233Sbschmidt DELAY(10); 2155235233Sbschmidt } 2156235233Sbschmidt if (ntries == 10) { 2157235233Sbschmidt device_printf(sc->sc_dev, "could not write to RF\n"); 2158235233Sbschmidt return; 2159235233Sbschmidt } 2160235233Sbschmidt 2161235233Sbschmidt tmp = RT3070_RF_WRITE | RT3070_RF_KICK | reg << 8 | val; 2162235233Sbschmidt RAL_WRITE(sc, RT3070_RF_CSR_CFG, tmp); 2163235233Sbschmidt} 2164235233Sbschmidt 2165235233Sbschmidt/* 2166235233Sbschmidt * Send a command to the 8051 microcontroller unit. 2167235233Sbschmidt */ 2168235233Sbschmidtint 2169235233Sbschmidtrt2860_mcu_cmd(struct rt2860_softc *sc, uint8_t cmd, uint16_t arg, int wait) 2170235233Sbschmidt{ 2171235233Sbschmidt int slot, ntries; 2172235233Sbschmidt uint32_t tmp; 2173235233Sbschmidt uint8_t cid; 2174235233Sbschmidt 2175235233Sbschmidt for (ntries = 0; ntries < 100; ntries++) { 2176235233Sbschmidt if (!(RAL_READ(sc, RT2860_H2M_MAILBOX) & RT2860_H2M_BUSY)) 2177235233Sbschmidt break; 2178235233Sbschmidt DELAY(2); 2179235233Sbschmidt } 2180235233Sbschmidt if (ntries == 100) 2181235233Sbschmidt return EIO; 2182235233Sbschmidt 2183235233Sbschmidt cid = wait ? cmd : RT2860_TOKEN_NO_INTR; 2184235233Sbschmidt RAL_WRITE(sc, RT2860_H2M_MAILBOX, RT2860_H2M_BUSY | cid << 16 | arg); 2185235233Sbschmidt RAL_BARRIER_WRITE(sc); 2186235233Sbschmidt RAL_WRITE(sc, RT2860_HOST_CMD, cmd); 2187235233Sbschmidt 2188235233Sbschmidt if (!wait) 2189235233Sbschmidt return 0; 2190235233Sbschmidt /* wait for the command to complete */ 2191235233Sbschmidt for (ntries = 0; ntries < 200; ntries++) { 2192235233Sbschmidt tmp = RAL_READ(sc, RT2860_H2M_MAILBOX_CID); 2193235233Sbschmidt /* find the command slot */ 2194235233Sbschmidt for (slot = 0; slot < 4; slot++, tmp >>= 8) 2195235233Sbschmidt if ((tmp & 0xff) == cid) 2196235233Sbschmidt break; 2197235233Sbschmidt if (slot < 4) 2198235233Sbschmidt break; 2199235233Sbschmidt DELAY(100); 2200235233Sbschmidt } 2201235233Sbschmidt if (ntries == 200) { 2202235233Sbschmidt /* clear command and status */ 2203235233Sbschmidt RAL_WRITE(sc, RT2860_H2M_MAILBOX_STATUS, 0xffffffff); 2204235233Sbschmidt RAL_WRITE(sc, RT2860_H2M_MAILBOX_CID, 0xffffffff); 2205235233Sbschmidt return ETIMEDOUT; 2206235233Sbschmidt } 2207235233Sbschmidt /* get command status (1 means success) */ 2208235233Sbschmidt tmp = RAL_READ(sc, RT2860_H2M_MAILBOX_STATUS); 2209235233Sbschmidt tmp = (tmp >> (slot * 8)) & 0xff; 2210235233Sbschmidt DPRINTF(("MCU command=0x%02x slot=%d status=0x%02x\n", 2211235233Sbschmidt cmd, slot, tmp)); 2212235233Sbschmidt /* clear command and status */ 2213235233Sbschmidt RAL_WRITE(sc, RT2860_H2M_MAILBOX_STATUS, 0xffffffff); 2214235233Sbschmidt RAL_WRITE(sc, RT2860_H2M_MAILBOX_CID, 0xffffffff); 2215235233Sbschmidt return (tmp == 1) ? 0 : EIO; 2216235233Sbschmidt} 2217235233Sbschmidt 2218235233Sbschmidtstatic void 2219235233Sbschmidtrt2860_enable_mrr(struct rt2860_softc *sc) 2220235233Sbschmidt{ 2221235233Sbschmidt#define CCK(mcs) (mcs) 2222235233Sbschmidt#define OFDM(mcs) (1 << 3 | (mcs)) 2223235233Sbschmidt RAL_WRITE(sc, RT2860_LG_FBK_CFG0, 2224235233Sbschmidt OFDM(6) << 28 | /* 54->48 */ 2225235233Sbschmidt OFDM(5) << 24 | /* 48->36 */ 2226235233Sbschmidt OFDM(4) << 20 | /* 36->24 */ 2227235233Sbschmidt OFDM(3) << 16 | /* 24->18 */ 2228235233Sbschmidt OFDM(2) << 12 | /* 18->12 */ 2229235233Sbschmidt OFDM(1) << 8 | /* 12-> 9 */ 2230235233Sbschmidt OFDM(0) << 4 | /* 9-> 6 */ 2231235233Sbschmidt OFDM(0)); /* 6-> 6 */ 2232235233Sbschmidt 2233235233Sbschmidt RAL_WRITE(sc, RT2860_LG_FBK_CFG1, 2234235233Sbschmidt CCK(2) << 12 | /* 11->5.5 */ 2235235233Sbschmidt CCK(1) << 8 | /* 5.5-> 2 */ 2236235233Sbschmidt CCK(0) << 4 | /* 2-> 1 */ 2237235233Sbschmidt CCK(0)); /* 1-> 1 */ 2238235233Sbschmidt#undef OFDM 2239235233Sbschmidt#undef CCK 2240235233Sbschmidt} 2241235233Sbschmidt 2242235233Sbschmidtstatic void 2243235233Sbschmidtrt2860_set_txpreamble(struct rt2860_softc *sc) 2244235233Sbschmidt{ 2245287197Sglebius struct ieee80211com *ic = &sc->sc_ic; 2246235233Sbschmidt uint32_t tmp; 2247235233Sbschmidt 2248235233Sbschmidt tmp = RAL_READ(sc, RT2860_AUTO_RSP_CFG); 2249235233Sbschmidt tmp &= ~RT2860_CCK_SHORT_EN; 2250235233Sbschmidt if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) 2251235233Sbschmidt tmp |= RT2860_CCK_SHORT_EN; 2252235233Sbschmidt RAL_WRITE(sc, RT2860_AUTO_RSP_CFG, tmp); 2253235233Sbschmidt} 2254235233Sbschmidt 2255235233Sbschmidtvoid 2256235233Sbschmidtrt2860_set_basicrates(struct rt2860_softc *sc, 2257235233Sbschmidt const struct ieee80211_rateset *rs) 2258235233Sbschmidt{ 2259287197Sglebius struct ieee80211com *ic = &sc->sc_ic; 2260235233Sbschmidt uint32_t mask = 0; 2261235233Sbschmidt uint8_t rate; 2262235233Sbschmidt int i; 2263235233Sbschmidt 2264235233Sbschmidt for (i = 0; i < rs->rs_nrates; i++) { 2265235233Sbschmidt rate = rs->rs_rates[i]; 2266235233Sbschmidt 2267235233Sbschmidt if (!(rate & IEEE80211_RATE_BASIC)) 2268235233Sbschmidt continue; 2269235233Sbschmidt 2270288087Sadrian mask |= 1 << ieee80211_legacy_rate_lookup(ic->ic_rt, 2271288087Sadrian IEEE80211_RV(rate)); 2272235233Sbschmidt } 2273235233Sbschmidt 2274235233Sbschmidt RAL_WRITE(sc, RT2860_LEGACY_BASIC_RATE, mask); 2275235233Sbschmidt} 2276235233Sbschmidt 2277235233Sbschmidtstatic void 2278235233Sbschmidtrt2860_scan_start(struct ieee80211com *ic) 2279235233Sbschmidt{ 2280287197Sglebius struct rt2860_softc *sc = ic->ic_softc; 2281235233Sbschmidt uint32_t tmp; 2282235233Sbschmidt 2283235233Sbschmidt tmp = RAL_READ(sc, RT2860_BCN_TIME_CFG); 2284235233Sbschmidt RAL_WRITE(sc, RT2860_BCN_TIME_CFG, 2285235233Sbschmidt tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN | 2286235233Sbschmidt RT2860_TBTT_TIMER_EN)); 2287235233Sbschmidt rt2860_set_gp_timer(sc, 0); 2288235233Sbschmidt} 2289235233Sbschmidt 2290235233Sbschmidtstatic void 2291235233Sbschmidtrt2860_scan_end(struct ieee80211com *ic) 2292235233Sbschmidt{ 2293287197Sglebius struct rt2860_softc *sc = ic->ic_softc; 2294235233Sbschmidt struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); 2295235233Sbschmidt 2296235233Sbschmidt if (vap->iv_state == IEEE80211_S_RUN) { 2297235233Sbschmidt rt2860_enable_tsf_sync(sc); 2298235233Sbschmidt rt2860_set_gp_timer(sc, 500); 2299235233Sbschmidt } 2300235233Sbschmidt} 2301235233Sbschmidt 2302235233Sbschmidtstatic void 2303300752Savosrt2860_getradiocaps(struct ieee80211com *ic, int maxchans, int *nchans, 2304300752Savos struct ieee80211_channel chans[]) 2305300752Savos{ 2306300752Savos struct rt2860_softc *sc = ic->ic_softc; 2307300752Savos uint8_t bands[IEEE80211_MODE_BYTES]; 2308300752Savos 2309300752Savos memset(bands, 0, sizeof(bands)); 2310300752Savos setbit(bands, IEEE80211_MODE_11B); 2311300752Savos setbit(bands, IEEE80211_MODE_11G); 2312343976Savos ieee80211_add_channels_default_2ghz(chans, maxchans, nchans, bands, 0); 2313300752Savos 2314300752Savos if (sc->rf_rev == RT2860_RF_2750 || sc->rf_rev == RT2860_RF_2850) { 2315300752Savos setbit(bands, IEEE80211_MODE_11A); 2316300752Savos ieee80211_add_channel_list_5ghz(chans, maxchans, nchans, 2317300752Savos rt2860_chan_5ghz, nitems(rt2860_chan_5ghz), bands, 0); 2318300752Savos } 2319300752Savos} 2320300752Savos 2321300752Savosstatic void 2322235233Sbschmidtrt2860_set_channel(struct ieee80211com *ic) 2323235233Sbschmidt{ 2324287197Sglebius struct rt2860_softc *sc = ic->ic_softc; 2325235233Sbschmidt 2326235233Sbschmidt RAL_LOCK(sc); 2327235233Sbschmidt rt2860_switch_chan(sc, ic->ic_curchan); 2328235233Sbschmidt RAL_UNLOCK(sc); 2329235233Sbschmidt} 2330235233Sbschmidt 2331235233Sbschmidtstatic void 2332235233Sbschmidtrt2860_select_chan_group(struct rt2860_softc *sc, int group) 2333235233Sbschmidt{ 2334235233Sbschmidt uint32_t tmp; 2335235233Sbschmidt uint8_t agc; 2336235233Sbschmidt 2337235233Sbschmidt rt2860_mcu_bbp_write(sc, 62, 0x37 - sc->lna[group]); 2338235233Sbschmidt rt2860_mcu_bbp_write(sc, 63, 0x37 - sc->lna[group]); 2339235233Sbschmidt rt2860_mcu_bbp_write(sc, 64, 0x37 - sc->lna[group]); 2340235233Sbschmidt rt2860_mcu_bbp_write(sc, 86, 0x00); 2341235233Sbschmidt 2342235233Sbschmidt if (group == 0) { 2343235233Sbschmidt if (sc->ext_2ghz_lna) { 2344235233Sbschmidt rt2860_mcu_bbp_write(sc, 82, 0x62); 2345235233Sbschmidt rt2860_mcu_bbp_write(sc, 75, 0x46); 2346235233Sbschmidt } else { 2347235233Sbschmidt rt2860_mcu_bbp_write(sc, 82, 0x84); 2348235233Sbschmidt rt2860_mcu_bbp_write(sc, 75, 0x50); 2349235233Sbschmidt } 2350235233Sbschmidt } else { 2351235233Sbschmidt if (sc->ext_5ghz_lna) { 2352235233Sbschmidt rt2860_mcu_bbp_write(sc, 82, 0xf2); 2353235233Sbschmidt rt2860_mcu_bbp_write(sc, 75, 0x46); 2354235233Sbschmidt } else { 2355235233Sbschmidt rt2860_mcu_bbp_write(sc, 82, 0xf2); 2356235233Sbschmidt rt2860_mcu_bbp_write(sc, 75, 0x50); 2357235233Sbschmidt } 2358235233Sbschmidt } 2359235233Sbschmidt 2360235233Sbschmidt tmp = RAL_READ(sc, RT2860_TX_BAND_CFG); 2361235233Sbschmidt tmp &= ~(RT2860_5G_BAND_SEL_N | RT2860_5G_BAND_SEL_P); 2362235233Sbschmidt tmp |= (group == 0) ? RT2860_5G_BAND_SEL_N : RT2860_5G_BAND_SEL_P; 2363235233Sbschmidt RAL_WRITE(sc, RT2860_TX_BAND_CFG, tmp); 2364235233Sbschmidt 2365235233Sbschmidt /* enable appropriate Power Amplifiers and Low Noise Amplifiers */ 2366235233Sbschmidt tmp = RT2860_RFTR_EN | RT2860_TRSW_EN | RT2860_LNA_PE0_EN; 2367235233Sbschmidt if (sc->nrxchains > 1) 2368235233Sbschmidt tmp |= RT2860_LNA_PE1_EN; 2369235233Sbschmidt if (sc->mac_ver == 0x3593 && sc->nrxchains > 2) 2370235233Sbschmidt tmp |= RT3593_LNA_PE2_EN; 2371235233Sbschmidt if (group == 0) { /* 2GHz */ 2372235233Sbschmidt tmp |= RT2860_PA_PE_G0_EN; 2373235233Sbschmidt if (sc->ntxchains > 1) 2374235233Sbschmidt tmp |= RT2860_PA_PE_G1_EN; 2375235233Sbschmidt if (sc->mac_ver == 0x3593 && sc->ntxchains > 2) 2376235233Sbschmidt tmp |= RT3593_PA_PE_G2_EN; 2377235233Sbschmidt } else { /* 5GHz */ 2378235233Sbschmidt tmp |= RT2860_PA_PE_A0_EN; 2379235233Sbschmidt if (sc->ntxchains > 1) 2380235233Sbschmidt tmp |= RT2860_PA_PE_A1_EN; 2381235233Sbschmidt if (sc->mac_ver == 0x3593 && sc->ntxchains > 2) 2382235233Sbschmidt tmp |= RT3593_PA_PE_A2_EN; 2383235233Sbschmidt } 2384235233Sbschmidt RAL_WRITE(sc, RT2860_TX_PIN_CFG, tmp); 2385235233Sbschmidt 2386235233Sbschmidt if (sc->mac_ver == 0x3593) { 2387235233Sbschmidt tmp = RAL_READ(sc, RT2860_GPIO_CTRL); 2388235233Sbschmidt if (sc->sc_flags & RT2860_PCIE) { 2389235233Sbschmidt tmp &= ~0x01010000; 2390235233Sbschmidt if (group == 0) 2391235233Sbschmidt tmp |= 0x00010000; 2392235233Sbschmidt } else { 2393235233Sbschmidt tmp &= ~0x00008080; 2394235233Sbschmidt if (group == 0) 2395235233Sbschmidt tmp |= 0x00000080; 2396235233Sbschmidt } 2397235233Sbschmidt tmp = (tmp & ~0x00001000) | 0x00000010; 2398235233Sbschmidt RAL_WRITE(sc, RT2860_GPIO_CTRL, tmp); 2399235233Sbschmidt } 2400235233Sbschmidt 2401235233Sbschmidt /* set initial AGC value */ 2402235233Sbschmidt if (group == 0) { /* 2GHz band */ 2403235233Sbschmidt if (sc->mac_ver >= 0x3071) 2404235233Sbschmidt agc = 0x1c + sc->lna[0] * 2; 2405235233Sbschmidt else 2406235233Sbschmidt agc = 0x2e + sc->lna[0]; 2407235233Sbschmidt } else { /* 5GHz band */ 2408235233Sbschmidt agc = 0x32 + (sc->lna[group] * 5) / 3; 2409235233Sbschmidt } 2410235233Sbschmidt rt2860_mcu_bbp_write(sc, 66, agc); 2411235233Sbschmidt 2412235233Sbschmidt DELAY(1000); 2413235233Sbschmidt} 2414235233Sbschmidt 2415235233Sbschmidtstatic void 2416235233Sbschmidtrt2860_set_chan(struct rt2860_softc *sc, u_int chan) 2417235233Sbschmidt{ 2418235233Sbschmidt const struct rfprog *rfprog = rt2860_rf2850; 2419235233Sbschmidt uint32_t r2, r3, r4; 2420235233Sbschmidt int8_t txpow1, txpow2; 2421235233Sbschmidt u_int i; 2422235233Sbschmidt 2423235233Sbschmidt /* find the settings for this channel (we know it exists) */ 2424235233Sbschmidt for (i = 0; rfprog[i].chan != chan; i++); 2425235233Sbschmidt 2426235233Sbschmidt r2 = rfprog[i].r2; 2427235233Sbschmidt if (sc->ntxchains == 1) 2428235233Sbschmidt r2 |= 1 << 12; /* 1T: disable Tx chain 2 */ 2429235233Sbschmidt if (sc->nrxchains == 1) 2430235233Sbschmidt r2 |= 1 << 15 | 1 << 4; /* 1R: disable Rx chains 2 & 3 */ 2431235233Sbschmidt else if (sc->nrxchains == 2) 2432235233Sbschmidt r2 |= 1 << 4; /* 2R: disable Rx chain 3 */ 2433235233Sbschmidt 2434235233Sbschmidt /* use Tx power values from EEPROM */ 2435235233Sbschmidt txpow1 = sc->txpow1[i]; 2436235233Sbschmidt txpow2 = sc->txpow2[i]; 2437235233Sbschmidt if (chan > 14) { 2438235233Sbschmidt if (txpow1 >= 0) 2439235233Sbschmidt txpow1 = txpow1 << 1 | 1; 2440235233Sbschmidt else 2441235233Sbschmidt txpow1 = (7 + txpow1) << 1; 2442235233Sbschmidt if (txpow2 >= 0) 2443235233Sbschmidt txpow2 = txpow2 << 1 | 1; 2444235233Sbschmidt else 2445235233Sbschmidt txpow2 = (7 + txpow2) << 1; 2446235233Sbschmidt } 2447235233Sbschmidt r3 = rfprog[i].r3 | txpow1 << 7; 2448235233Sbschmidt r4 = rfprog[i].r4 | sc->freq << 13 | txpow2 << 4; 2449235233Sbschmidt 2450235233Sbschmidt rt2860_rf_write(sc, RT2860_RF1, rfprog[i].r1); 2451235233Sbschmidt rt2860_rf_write(sc, RT2860_RF2, r2); 2452235233Sbschmidt rt2860_rf_write(sc, RT2860_RF3, r3); 2453235233Sbschmidt rt2860_rf_write(sc, RT2860_RF4, r4); 2454235233Sbschmidt 2455235233Sbschmidt DELAY(200); 2456235233Sbschmidt 2457235233Sbschmidt rt2860_rf_write(sc, RT2860_RF1, rfprog[i].r1); 2458235233Sbschmidt rt2860_rf_write(sc, RT2860_RF2, r2); 2459235233Sbschmidt rt2860_rf_write(sc, RT2860_RF3, r3 | 1); 2460235233Sbschmidt rt2860_rf_write(sc, RT2860_RF4, r4); 2461235233Sbschmidt 2462235233Sbschmidt DELAY(200); 2463235233Sbschmidt 2464235233Sbschmidt rt2860_rf_write(sc, RT2860_RF1, rfprog[i].r1); 2465235233Sbschmidt rt2860_rf_write(sc, RT2860_RF2, r2); 2466235233Sbschmidt rt2860_rf_write(sc, RT2860_RF3, r3); 2467235233Sbschmidt rt2860_rf_write(sc, RT2860_RF4, r4); 2468235233Sbschmidt} 2469235233Sbschmidt 2470235233Sbschmidtstatic void 2471235233Sbschmidtrt3090_set_chan(struct rt2860_softc *sc, u_int chan) 2472235233Sbschmidt{ 2473235233Sbschmidt int8_t txpow1, txpow2; 2474235233Sbschmidt uint8_t rf; 2475235233Sbschmidt int i; 2476235233Sbschmidt 2477235233Sbschmidt /* RT3090 is 2GHz only */ 2478235233Sbschmidt KASSERT(chan >= 1 && chan <= 14, ("chan %d not support", chan)); 2479235233Sbschmidt 2480235233Sbschmidt /* find the settings for this channel (we know it exists) */ 2481235233Sbschmidt for (i = 0; rt2860_rf2850[i].chan != chan; i++); 2482235233Sbschmidt 2483235233Sbschmidt /* use Tx power values from EEPROM */ 2484235233Sbschmidt txpow1 = sc->txpow1[i]; 2485235233Sbschmidt txpow2 = sc->txpow2[i]; 2486235233Sbschmidt 2487235233Sbschmidt rt3090_rf_write(sc, 2, rt3090_freqs[i].n); 2488235233Sbschmidt rf = rt3090_rf_read(sc, 3); 2489235233Sbschmidt rf = (rf & ~0x0f) | rt3090_freqs[i].k; 2490235233Sbschmidt rt3090_rf_write(sc, 3, rf); 2491235233Sbschmidt rf = rt3090_rf_read(sc, 6); 2492235233Sbschmidt rf = (rf & ~0x03) | rt3090_freqs[i].r; 2493235233Sbschmidt rt3090_rf_write(sc, 6, rf); 2494235233Sbschmidt 2495235233Sbschmidt /* set Tx0 power */ 2496235233Sbschmidt rf = rt3090_rf_read(sc, 12); 2497235233Sbschmidt rf = (rf & ~0x1f) | txpow1; 2498235233Sbschmidt rt3090_rf_write(sc, 12, rf); 2499235233Sbschmidt 2500235233Sbschmidt /* set Tx1 power */ 2501235233Sbschmidt rf = rt3090_rf_read(sc, 13); 2502235233Sbschmidt rf = (rf & ~0x1f) | txpow2; 2503235233Sbschmidt rt3090_rf_write(sc, 13, rf); 2504235233Sbschmidt 2505235233Sbschmidt rf = rt3090_rf_read(sc, 1); 2506235233Sbschmidt rf &= ~0xfc; 2507235233Sbschmidt if (sc->ntxchains == 1) 2508235233Sbschmidt rf |= RT3070_TX1_PD | RT3070_TX2_PD; 2509235233Sbschmidt else if (sc->ntxchains == 2) 2510235233Sbschmidt rf |= RT3070_TX2_PD; 2511235233Sbschmidt if (sc->nrxchains == 1) 2512235233Sbschmidt rf |= RT3070_RX1_PD | RT3070_RX2_PD; 2513235233Sbschmidt else if (sc->nrxchains == 2) 2514235233Sbschmidt rf |= RT3070_RX2_PD; 2515235233Sbschmidt rt3090_rf_write(sc, 1, rf); 2516235233Sbschmidt 2517235233Sbschmidt /* set RF offset */ 2518235233Sbschmidt rf = rt3090_rf_read(sc, 23); 2519235233Sbschmidt rf = (rf & ~0x7f) | sc->freq; 2520235233Sbschmidt rt3090_rf_write(sc, 23, rf); 2521235233Sbschmidt 2522235233Sbschmidt /* program RF filter */ 2523235233Sbschmidt rf = rt3090_rf_read(sc, 24); /* Tx */ 2524235233Sbschmidt rf = (rf & ~0x3f) | sc->rf24_20mhz; 2525235233Sbschmidt rt3090_rf_write(sc, 24, rf); 2526235233Sbschmidt rf = rt3090_rf_read(sc, 31); /* Rx */ 2527235233Sbschmidt rf = (rf & ~0x3f) | sc->rf24_20mhz; 2528235233Sbschmidt rt3090_rf_write(sc, 31, rf); 2529235233Sbschmidt 2530235233Sbschmidt /* enable RF tuning */ 2531235233Sbschmidt rf = rt3090_rf_read(sc, 7); 2532235233Sbschmidt rt3090_rf_write(sc, 7, rf | RT3070_TUNE); 2533235233Sbschmidt} 2534235233Sbschmidt 2535278551Skevlostatic void 2536278551Skevlort5390_set_chan(struct rt2860_softc *sc, u_int chan) 2537278551Skevlo{ 2538278551Skevlo uint8_t h20mhz, rf, tmp; 2539278551Skevlo int8_t txpow1, txpow2; 2540278551Skevlo int i; 2541278551Skevlo 2542278551Skevlo /* RT5390 is 2GHz only */ 2543278551Skevlo KASSERT(chan >= 1 && chan <= 14, ("chan %d not support", chan)); 2544278551Skevlo 2545278551Skevlo /* find the settings for this channel (we know it exists) */ 2546278551Skevlo for (i = 0; rt2860_rf2850[i].chan != chan; i++); 2547278551Skevlo 2548278551Skevlo /* use Tx power values from EEPROM */ 2549278551Skevlo txpow1 = sc->txpow1[i]; 2550278551Skevlo txpow2 = sc->txpow2[i]; 2551278551Skevlo 2552278551Skevlo rt3090_rf_write(sc, 8, rt3090_freqs[i].n); 2553278551Skevlo rt3090_rf_write(sc, 9, rt3090_freqs[i].k & 0x0f); 2554278551Skevlo rf = rt3090_rf_read(sc, 11); 2555278551Skevlo rf = (rf & ~0x03) | (rt3090_freqs[i].r & 0x03); 2556278551Skevlo rt3090_rf_write(sc, 11, rf); 2557278551Skevlo 2558278551Skevlo rf = rt3090_rf_read(sc, 49); 2559278551Skevlo rf = (rf & ~0x3f) | (txpow1 & 0x3f); 2560278551Skevlo /* the valid range of the RF R49 is 0x00~0x27 */ 2561278551Skevlo if ((rf & 0x3f) > 0x27) 2562278551Skevlo rf = (rf & ~0x3f) | 0x27; 2563278551Skevlo rt3090_rf_write(sc, 49, rf); 2564278551Skevlo if (sc->mac_ver == 0x5392) { 2565278551Skevlo rf = rt3090_rf_read(sc, 50); 2566278551Skevlo rf = (rf & ~0x3f) | (txpow2 & 0x3f); 2567278551Skevlo /* the valid range of the RF R50 is 0x00~0x27 */ 2568278551Skevlo if ((rf & 0x3f) > 0x27) 2569278551Skevlo rf = (rf & ~0x3f) | 0x27; 2570278551Skevlo rt3090_rf_write(sc, 50, rf); 2571278551Skevlo } 2572278551Skevlo 2573278551Skevlo rf = rt3090_rf_read(sc, 1); 2574278551Skevlo rf |= RT3070_RF_BLOCK | RT3070_PLL_PD | RT3070_RX0_PD | RT3070_TX0_PD; 2575278551Skevlo if (sc->mac_ver == 0x5392) 2576278551Skevlo rf |= RT3070_RX1_PD | RT3070_TX1_PD; 2577278551Skevlo rt3090_rf_write(sc, 1, rf); 2578278551Skevlo 2579278551Skevlo rf = rt3090_rf_read(sc, 2); 2580278551Skevlo rt3090_rf_write(sc, 2, rf | RT3593_RESCAL); 2581278551Skevlo DELAY(1000); 2582278551Skevlo rt3090_rf_write(sc, 2, rf & ~RT3593_RESCAL); 2583278551Skevlo 2584278551Skevlo rf = rt3090_rf_read(sc, 17); 2585278551Skevlo tmp = rf; 2586278551Skevlo rf = (rf & ~0x7f) | (sc->freq & 0x7f); 2587278551Skevlo rf = MIN(rf, 0x5f); 2588278551Skevlo if (tmp != rf) 2589278551Skevlo rt2860_mcu_cmd(sc, 0x74, (tmp << 8 ) | rf, 0); 2590278551Skevlo 2591278551Skevlo if (sc->mac_ver == 0x5390) { 2592278551Skevlo if (chan <= 4) 2593278551Skevlo rf = 0x73; 2594278551Skevlo else if (chan >= 5 && chan <= 6) 2595278551Skevlo rf = 0x63; 2596278551Skevlo else if (chan >= 7 && chan <= 10) 2597278551Skevlo rf = 0x53; 2598278551Skevlo else 2599278551Skevlo rf = 43; 2600278551Skevlo rt3090_rf_write(sc, 55, rf); 2601278551Skevlo 2602278551Skevlo if (chan == 1) 2603278551Skevlo rf = 0x0c; 2604278551Skevlo else if (chan == 2) 2605278551Skevlo rf = 0x0b; 2606278551Skevlo else if (chan == 3) 2607278551Skevlo rf = 0x0a; 2608278551Skevlo else if (chan >= 4 && chan <= 6) 2609278551Skevlo rf = 0x09; 2610278551Skevlo else if (chan >= 7 && chan <= 12) 2611278551Skevlo rf = 0x08; 2612278551Skevlo else if (chan == 13) 2613278551Skevlo rf = 0x07; 2614278551Skevlo else 2615278551Skevlo rf = 0x06; 2616278551Skevlo rt3090_rf_write(sc, 59, rf); 2617278551Skevlo } 2618278551Skevlo 2619278551Skevlo /* Tx/Rx h20M */ 2620278551Skevlo h20mhz = (sc->rf24_20mhz & 0x20) >> 5; 2621278551Skevlo rf = rt3090_rf_read(sc, 30); 2622278551Skevlo rf = (rf & ~0x06) | (h20mhz << 1) | (h20mhz << 2); 2623278551Skevlo rt3090_rf_write(sc, 30, rf); 2624278551Skevlo 2625278551Skevlo /* Rx BB filter VCM */ 2626278551Skevlo rf = rt3090_rf_read(sc, 30); 2627278551Skevlo rf = (rf & ~0x18) | 0x10; 2628278551Skevlo rt3090_rf_write(sc, 30, rf); 2629278551Skevlo 2630278551Skevlo /* Initiate VCO calibration. */ 2631278551Skevlo rf = rt3090_rf_read(sc, 3); 2632278551Skevlo rf |= RT3593_VCOCAL; 2633278551Skevlo rt3090_rf_write(sc, 3, rf); 2634278551Skevlo} 2635278551Skevlo 2636235233Sbschmidtstatic int 2637235233Sbschmidtrt3090_rf_init(struct rt2860_softc *sc) 2638235233Sbschmidt{ 2639235233Sbschmidt uint32_t tmp; 2640235233Sbschmidt uint8_t rf, bbp; 2641235233Sbschmidt int i; 2642235233Sbschmidt 2643235233Sbschmidt rf = rt3090_rf_read(sc, 30); 2644235233Sbschmidt /* toggle RF R30 bit 7 */ 2645235233Sbschmidt rt3090_rf_write(sc, 30, rf | 0x80); 2646235233Sbschmidt DELAY(1000); 2647235233Sbschmidt rt3090_rf_write(sc, 30, rf & ~0x80); 2648235233Sbschmidt 2649235233Sbschmidt tmp = RAL_READ(sc, RT3070_LDO_CFG0); 2650235233Sbschmidt tmp &= ~0x1f000000; 2651235233Sbschmidt if (sc->patch_dac && sc->mac_rev < 0x0211) 2652235233Sbschmidt tmp |= 0x0d000000; /* 1.35V */ 2653235233Sbschmidt else 2654235233Sbschmidt tmp |= 0x01000000; /* 1.2V */ 2655235233Sbschmidt RAL_WRITE(sc, RT3070_LDO_CFG0, tmp); 2656235233Sbschmidt 2657235233Sbschmidt /* patch LNA_PE_G1 */ 2658235233Sbschmidt tmp = RAL_READ(sc, RT3070_GPIO_SWITCH); 2659235233Sbschmidt RAL_WRITE(sc, RT3070_GPIO_SWITCH, tmp & ~0x20); 2660235233Sbschmidt 2661235233Sbschmidt /* initialize RF registers to default value */ 2662278551Skevlo for (i = 0; i < nitems(rt3090_def_rf); i++) { 2663235233Sbschmidt rt3090_rf_write(sc, rt3090_def_rf[i].reg, 2664235233Sbschmidt rt3090_def_rf[i].val); 2665235233Sbschmidt } 2666235233Sbschmidt 2667235233Sbschmidt /* select 20MHz bandwidth */ 2668235233Sbschmidt rt3090_rf_write(sc, 31, 0x14); 2669235233Sbschmidt 2670235233Sbschmidt rf = rt3090_rf_read(sc, 6); 2671235233Sbschmidt rt3090_rf_write(sc, 6, rf | 0x40); 2672235233Sbschmidt 2673235233Sbschmidt if (sc->mac_ver != 0x3593) { 2674235233Sbschmidt /* calibrate filter for 20MHz bandwidth */ 2675235233Sbschmidt sc->rf24_20mhz = 0x1f; /* default value */ 2676235233Sbschmidt rt3090_filter_calib(sc, 0x07, 0x16, &sc->rf24_20mhz); 2677235233Sbschmidt 2678235233Sbschmidt /* select 40MHz bandwidth */ 2679235233Sbschmidt bbp = rt2860_mcu_bbp_read(sc, 4); 2680235233Sbschmidt rt2860_mcu_bbp_write(sc, 4, (bbp & ~0x08) | 0x10); 2681235233Sbschmidt rf = rt3090_rf_read(sc, 31); 2682235233Sbschmidt rt3090_rf_write(sc, 31, rf | 0x20); 2683235233Sbschmidt 2684235233Sbschmidt /* calibrate filter for 40MHz bandwidth */ 2685235233Sbschmidt sc->rf24_40mhz = 0x2f; /* default value */ 2686235233Sbschmidt rt3090_filter_calib(sc, 0x27, 0x19, &sc->rf24_40mhz); 2687235233Sbschmidt 2688235233Sbschmidt /* go back to 20MHz bandwidth */ 2689235233Sbschmidt bbp = rt2860_mcu_bbp_read(sc, 4); 2690235233Sbschmidt rt2860_mcu_bbp_write(sc, 4, bbp & ~0x18); 2691235233Sbschmidt } 2692235233Sbschmidt if (sc->mac_rev < 0x0211) 2693235233Sbschmidt rt3090_rf_write(sc, 27, 0x03); 2694235233Sbschmidt 2695235233Sbschmidt tmp = RAL_READ(sc, RT3070_OPT_14); 2696235233Sbschmidt RAL_WRITE(sc, RT3070_OPT_14, tmp | 1); 2697235233Sbschmidt 2698235233Sbschmidt if (sc->rf_rev == RT3070_RF_3020) 2699235233Sbschmidt rt3090_set_rx_antenna(sc, 0); 2700235233Sbschmidt 2701235233Sbschmidt bbp = rt2860_mcu_bbp_read(sc, 138); 2702235233Sbschmidt if (sc->mac_ver == 0x3593) { 2703235233Sbschmidt if (sc->ntxchains == 1) 2704235233Sbschmidt bbp |= 0x60; /* turn off DAC1 and DAC2 */ 2705235233Sbschmidt else if (sc->ntxchains == 2) 2706235233Sbschmidt bbp |= 0x40; /* turn off DAC2 */ 2707235233Sbschmidt if (sc->nrxchains == 1) 2708235233Sbschmidt bbp &= ~0x06; /* turn off ADC1 and ADC2 */ 2709235233Sbschmidt else if (sc->nrxchains == 2) 2710235233Sbschmidt bbp &= ~0x04; /* turn off ADC2 */ 2711235233Sbschmidt } else { 2712235233Sbschmidt if (sc->ntxchains == 1) 2713235233Sbschmidt bbp |= 0x20; /* turn off DAC1 */ 2714235233Sbschmidt if (sc->nrxchains == 1) 2715235233Sbschmidt bbp &= ~0x02; /* turn off ADC1 */ 2716235233Sbschmidt } 2717235233Sbschmidt rt2860_mcu_bbp_write(sc, 138, bbp); 2718235233Sbschmidt 2719235233Sbschmidt rf = rt3090_rf_read(sc, 1); 2720235233Sbschmidt rf &= ~(RT3070_RX0_PD | RT3070_TX0_PD); 2721235233Sbschmidt rf |= RT3070_RF_BLOCK | RT3070_RX1_PD | RT3070_TX1_PD; 2722235233Sbschmidt rt3090_rf_write(sc, 1, rf); 2723235233Sbschmidt 2724235233Sbschmidt rf = rt3090_rf_read(sc, 15); 2725235233Sbschmidt rt3090_rf_write(sc, 15, rf & ~RT3070_TX_LO2); 2726235233Sbschmidt 2727235233Sbschmidt rf = rt3090_rf_read(sc, 17); 2728235233Sbschmidt rf &= ~RT3070_TX_LO1; 2729235233Sbschmidt if (sc->mac_rev >= 0x0211 && !sc->ext_2ghz_lna) 2730235233Sbschmidt rf |= 0x20; /* fix for long range Rx issue */ 2731235233Sbschmidt if (sc->txmixgain_2ghz >= 2) 2732235233Sbschmidt rf = (rf & ~0x7) | sc->txmixgain_2ghz; 2733235233Sbschmidt rt3090_rf_write(sc, 17, rf); 2734235233Sbschmidt 2735235233Sbschmidt rf = rt3090_rf_read(sc, 20); 2736235233Sbschmidt rt3090_rf_write(sc, 20, rf & ~RT3070_RX_LO1); 2737235233Sbschmidt 2738235233Sbschmidt rf = rt3090_rf_read(sc, 21); 2739235233Sbschmidt rt3090_rf_write(sc, 21, rf & ~RT3070_RX_LO2); 2740235233Sbschmidt 2741278551Skevlo return (0); 2742235233Sbschmidt} 2743235233Sbschmidt 2744278551Skevlostatic void 2745278551Skevlort5390_rf_init(struct rt2860_softc *sc) 2746278551Skevlo{ 2747278551Skevlo uint8_t rf, bbp; 2748278551Skevlo int i; 2749278551Skevlo 2750278551Skevlo rf = rt3090_rf_read(sc, 2); 2751278551Skevlo /* Toggle RF R2 bit 7. */ 2752278551Skevlo rt3090_rf_write(sc, 2, rf | RT3593_RESCAL); 2753278551Skevlo DELAY(1000); 2754278551Skevlo rt3090_rf_write(sc, 2, rf & ~RT3593_RESCAL); 2755278551Skevlo 2756278551Skevlo /* Initialize RF registers to default value. */ 2757278551Skevlo if (sc->mac_ver == 0x5392) { 2758278551Skevlo for (i = 0; i < nitems(rt5392_def_rf); i++) { 2759278551Skevlo rt3090_rf_write(sc, rt5392_def_rf[i].reg, 2760278551Skevlo rt5392_def_rf[i].val); 2761278551Skevlo } 2762278551Skevlo } else { 2763278551Skevlo for (i = 0; i < nitems(rt5390_def_rf); i++) { 2764278551Skevlo rt3090_rf_write(sc, rt5390_def_rf[i].reg, 2765278551Skevlo rt5390_def_rf[i].val); 2766278551Skevlo } 2767278551Skevlo } 2768278551Skevlo 2769278551Skevlo sc->rf24_20mhz = 0x1f; 2770278551Skevlo sc->rf24_40mhz = 0x2f; 2771278551Skevlo 2772278551Skevlo if (sc->mac_rev < 0x0211) 2773278551Skevlo rt3090_rf_write(sc, 27, 0x03); 2774278551Skevlo 2775278551Skevlo /* Set led open drain enable. */ 2776278551Skevlo RAL_WRITE(sc, RT3070_OPT_14, RAL_READ(sc, RT3070_OPT_14) | 1); 2777278551Skevlo 2778278551Skevlo RAL_WRITE(sc, RT2860_TX_SW_CFG1, 0); 2779278551Skevlo RAL_WRITE(sc, RT2860_TX_SW_CFG2, 0); 2780278551Skevlo 2781278551Skevlo if (sc->mac_ver == 0x5390) 2782278551Skevlo rt3090_set_rx_antenna(sc, 0); 2783278551Skevlo 2784278551Skevlo /* Patch RSSI inaccurate issue. */ 2785278551Skevlo rt2860_mcu_bbp_write(sc, 79, 0x13); 2786278551Skevlo rt2860_mcu_bbp_write(sc, 80, 0x05); 2787278551Skevlo rt2860_mcu_bbp_write(sc, 81, 0x33); 2788278551Skevlo 2789278551Skevlo /* Enable DC filter. */ 2790278551Skevlo if (sc->mac_rev >= 0x0211) 2791278551Skevlo rt2860_mcu_bbp_write(sc, 103, 0xc0); 2792278551Skevlo 2793278551Skevlo bbp = rt2860_mcu_bbp_read(sc, 138); 2794278551Skevlo if (sc->ntxchains == 1) 2795278551Skevlo bbp |= 0x20; /* Turn off DAC1. */ 2796278551Skevlo if (sc->nrxchains == 1) 2797278551Skevlo bbp &= ~0x02; /* Turn off ADC1. */ 2798278551Skevlo rt2860_mcu_bbp_write(sc, 138, bbp); 2799278551Skevlo 2800278551Skevlo /* Enable RX LO1 and LO2. */ 2801278551Skevlo rt3090_rf_write(sc, 38, rt3090_rf_read(sc, 38) & ~RT5390_RX_LO1); 2802278551Skevlo rt3090_rf_write(sc, 39, rt3090_rf_read(sc, 39) & ~RT5390_RX_LO2); 2803278551Skevlo 2804278551Skevlo /* Avoid data lost and CRC error. */ 2805278551Skevlo rt2860_mcu_bbp_write(sc, 4, 2806278551Skevlo rt2860_mcu_bbp_read(sc, 4) | RT5390_MAC_IF_CTRL); 2807278551Skevlo 2808278551Skevlo rf = rt3090_rf_read(sc, 30); 2809278551Skevlo rf = (rf & ~0x18) | 0x10; 2810278551Skevlo rt3090_rf_write(sc, 30, rf); 2811278551Skevlo} 2812278551Skevlo 2813278551Skevlostatic void 2814235233Sbschmidtrt3090_rf_wakeup(struct rt2860_softc *sc) 2815235233Sbschmidt{ 2816235233Sbschmidt uint32_t tmp; 2817235233Sbschmidt uint8_t rf; 2818235233Sbschmidt 2819235233Sbschmidt if (sc->mac_ver == 0x3593) { 2820235233Sbschmidt /* enable VCO */ 2821235233Sbschmidt rf = rt3090_rf_read(sc, 1); 2822235233Sbschmidt rt3090_rf_write(sc, 1, rf | RT3593_VCO); 2823235233Sbschmidt 2824235233Sbschmidt /* initiate VCO calibration */ 2825235233Sbschmidt rf = rt3090_rf_read(sc, 3); 2826235233Sbschmidt rt3090_rf_write(sc, 3, rf | RT3593_VCOCAL); 2827235233Sbschmidt 2828235233Sbschmidt /* enable VCO bias current control */ 2829235233Sbschmidt rf = rt3090_rf_read(sc, 6); 2830235233Sbschmidt rt3090_rf_write(sc, 6, rf | RT3593_VCO_IC); 2831235233Sbschmidt 2832235233Sbschmidt /* initiate res calibration */ 2833235233Sbschmidt rf = rt3090_rf_read(sc, 2); 2834235233Sbschmidt rt3090_rf_write(sc, 2, rf | RT3593_RESCAL); 2835235233Sbschmidt 2836235233Sbschmidt /* set reference current control to 0.33 mA */ 2837235233Sbschmidt rf = rt3090_rf_read(sc, 22); 2838235233Sbschmidt rf &= ~RT3593_CP_IC_MASK; 2839235233Sbschmidt rf |= 1 << RT3593_CP_IC_SHIFT; 2840235233Sbschmidt rt3090_rf_write(sc, 22, rf); 2841235233Sbschmidt 2842235233Sbschmidt /* enable RX CTB */ 2843235233Sbschmidt rf = rt3090_rf_read(sc, 46); 2844235233Sbschmidt rt3090_rf_write(sc, 46, rf | RT3593_RX_CTB); 2845235233Sbschmidt 2846235233Sbschmidt rf = rt3090_rf_read(sc, 20); 2847235233Sbschmidt rf &= ~(RT3593_LDO_RF_VC_MASK | RT3593_LDO_PLL_VC_MASK); 2848235233Sbschmidt rt3090_rf_write(sc, 20, rf); 2849235233Sbschmidt } else { 2850235233Sbschmidt /* enable RF block */ 2851235233Sbschmidt rf = rt3090_rf_read(sc, 1); 2852235233Sbschmidt rt3090_rf_write(sc, 1, rf | RT3070_RF_BLOCK); 2853235233Sbschmidt 2854235233Sbschmidt /* enable VCO bias current control */ 2855235233Sbschmidt rf = rt3090_rf_read(sc, 7); 2856235233Sbschmidt rt3090_rf_write(sc, 7, rf | 0x30); 2857235233Sbschmidt 2858235233Sbschmidt rf = rt3090_rf_read(sc, 9); 2859235233Sbschmidt rt3090_rf_write(sc, 9, rf | 0x0e); 2860235233Sbschmidt 2861235233Sbschmidt /* enable RX CTB */ 2862235233Sbschmidt rf = rt3090_rf_read(sc, 21); 2863235233Sbschmidt rt3090_rf_write(sc, 21, rf | RT3070_RX_CTB); 2864235233Sbschmidt 2865235233Sbschmidt /* fix Tx to Rx IQ glitch by raising RF voltage */ 2866235233Sbschmidt rf = rt3090_rf_read(sc, 27); 2867235233Sbschmidt rf &= ~0x77; 2868235233Sbschmidt if (sc->mac_rev < 0x0211) 2869235233Sbschmidt rf |= 0x03; 2870235233Sbschmidt rt3090_rf_write(sc, 27, rf); 2871235233Sbschmidt } 2872235233Sbschmidt if (sc->patch_dac && sc->mac_rev < 0x0211) { 2873235233Sbschmidt tmp = RAL_READ(sc, RT3070_LDO_CFG0); 2874235233Sbschmidt tmp = (tmp & ~0x1f000000) | 0x0d000000; 2875235233Sbschmidt RAL_WRITE(sc, RT3070_LDO_CFG0, tmp); 2876235233Sbschmidt } 2877235233Sbschmidt} 2878235233Sbschmidt 2879278551Skevlostatic void 2880278551Skevlort5390_rf_wakeup(struct rt2860_softc *sc) 2881278551Skevlo{ 2882278551Skevlo uint32_t tmp; 2883278551Skevlo uint8_t rf; 2884278551Skevlo 2885278551Skevlo rf = rt3090_rf_read(sc, 1); 2886278551Skevlo rf |= RT3070_RF_BLOCK | RT3070_PLL_PD | RT3070_RX0_PD | 2887278551Skevlo RT3070_TX0_PD; 2888278551Skevlo if (sc->mac_ver == 0x5392) 2889278551Skevlo rf |= RT3070_RX1_PD | RT3070_TX1_PD; 2890278551Skevlo rt3090_rf_write(sc, 1, rf); 2891278551Skevlo 2892278551Skevlo rf = rt3090_rf_read(sc, 6); 2893278551Skevlo rf |= RT3593_VCO_IC | RT3593_VCOCAL; 2894278551Skevlo if (sc->mac_ver == 0x5390) 2895278551Skevlo rf &= ~RT3593_VCO_IC; 2896278551Skevlo rt3090_rf_write(sc, 6, rf); 2897278551Skevlo 2898278551Skevlo rt3090_rf_write(sc, 2, rt3090_rf_read(sc, 2) | RT3593_RESCAL); 2899278551Skevlo 2900278551Skevlo rf = rt3090_rf_read(sc, 22); 2901278551Skevlo rf = (rf & ~0xe0) | 0x20; 2902278551Skevlo rt3090_rf_write(sc, 22, rf); 2903278551Skevlo 2904278551Skevlo rt3090_rf_write(sc, 42, rt3090_rf_read(sc, 42) | RT5390_RX_CTB); 2905278551Skevlo rt3090_rf_write(sc, 20, rt3090_rf_read(sc, 20) & ~0x77); 2906278551Skevlo rt3090_rf_write(sc, 3, rt3090_rf_read(sc, 3) | RT3593_VCOCAL); 2907278551Skevlo 2908278551Skevlo if (sc->patch_dac && sc->mac_rev < 0x0211) { 2909278551Skevlo tmp = RAL_READ(sc, RT3070_LDO_CFG0); 2910278551Skevlo tmp = (tmp & ~0x1f000000) | 0x0d000000; 2911278551Skevlo RAL_WRITE(sc, RT3070_LDO_CFG0, tmp); 2912278551Skevlo } 2913278551Skevlo} 2914278551Skevlo 2915278551Skevlostatic int 2916235233Sbschmidtrt3090_filter_calib(struct rt2860_softc *sc, uint8_t init, uint8_t target, 2917235233Sbschmidt uint8_t *val) 2918235233Sbschmidt{ 2919235233Sbschmidt uint8_t rf22, rf24; 2920235233Sbschmidt uint8_t bbp55_pb, bbp55_sb, delta; 2921235233Sbschmidt int ntries; 2922235233Sbschmidt 2923235233Sbschmidt /* program filter */ 2924235233Sbschmidt rf24 = rt3090_rf_read(sc, 24); 2925235233Sbschmidt rf24 = (rf24 & 0xc0) | init; /* initial filter value */ 2926235233Sbschmidt rt3090_rf_write(sc, 24, rf24); 2927235233Sbschmidt 2928235233Sbschmidt /* enable baseband loopback mode */ 2929235233Sbschmidt rf22 = rt3090_rf_read(sc, 22); 2930235233Sbschmidt rt3090_rf_write(sc, 22, rf22 | RT3070_BB_LOOPBACK); 2931235233Sbschmidt 2932235233Sbschmidt /* set power and frequency of passband test tone */ 2933235233Sbschmidt rt2860_mcu_bbp_write(sc, 24, 0x00); 2934235233Sbschmidt for (ntries = 0; ntries < 100; ntries++) { 2935235233Sbschmidt /* transmit test tone */ 2936235233Sbschmidt rt2860_mcu_bbp_write(sc, 25, 0x90); 2937235233Sbschmidt DELAY(1000); 2938235233Sbschmidt /* read received power */ 2939235233Sbschmidt bbp55_pb = rt2860_mcu_bbp_read(sc, 55); 2940235233Sbschmidt if (bbp55_pb != 0) 2941235233Sbschmidt break; 2942235233Sbschmidt } 2943235233Sbschmidt if (ntries == 100) 2944278551Skevlo return (ETIMEDOUT); 2945235233Sbschmidt 2946235233Sbschmidt /* set power and frequency of stopband test tone */ 2947235233Sbschmidt rt2860_mcu_bbp_write(sc, 24, 0x06); 2948235233Sbschmidt for (ntries = 0; ntries < 100; ntries++) { 2949235233Sbschmidt /* transmit test tone */ 2950235233Sbschmidt rt2860_mcu_bbp_write(sc, 25, 0x90); 2951235233Sbschmidt DELAY(1000); 2952235233Sbschmidt /* read received power */ 2953235233Sbschmidt bbp55_sb = rt2860_mcu_bbp_read(sc, 55); 2954235233Sbschmidt 2955235233Sbschmidt delta = bbp55_pb - bbp55_sb; 2956235233Sbschmidt if (delta > target) 2957235233Sbschmidt break; 2958235233Sbschmidt 2959235233Sbschmidt /* reprogram filter */ 2960235233Sbschmidt rf24++; 2961235233Sbschmidt rt3090_rf_write(sc, 24, rf24); 2962235233Sbschmidt } 2963235233Sbschmidt if (ntries < 100) { 2964235233Sbschmidt if (rf24 != init) 2965235233Sbschmidt rf24--; /* backtrack */ 2966235233Sbschmidt *val = rf24; 2967235233Sbschmidt rt3090_rf_write(sc, 24, rf24); 2968235233Sbschmidt } 2969235233Sbschmidt 2970235233Sbschmidt /* restore initial state */ 2971235233Sbschmidt rt2860_mcu_bbp_write(sc, 24, 0x00); 2972235233Sbschmidt 2973235233Sbschmidt /* disable baseband loopback mode */ 2974235233Sbschmidt rf22 = rt3090_rf_read(sc, 22); 2975235233Sbschmidt rt3090_rf_write(sc, 22, rf22 & ~RT3070_BB_LOOPBACK); 2976235233Sbschmidt 2977278551Skevlo return (0); 2978235233Sbschmidt} 2979235233Sbschmidt 2980235233Sbschmidtstatic void 2981235233Sbschmidtrt3090_rf_setup(struct rt2860_softc *sc) 2982235233Sbschmidt{ 2983235233Sbschmidt uint8_t bbp; 2984235233Sbschmidt int i; 2985235233Sbschmidt 2986235233Sbschmidt if (sc->mac_rev >= 0x0211) { 2987235233Sbschmidt /* enable DC filter */ 2988235233Sbschmidt rt2860_mcu_bbp_write(sc, 103, 0xc0); 2989235233Sbschmidt 2990235233Sbschmidt /* improve power consumption */ 2991235233Sbschmidt bbp = rt2860_mcu_bbp_read(sc, 31); 2992235233Sbschmidt rt2860_mcu_bbp_write(sc, 31, bbp & ~0x03); 2993235233Sbschmidt } 2994235233Sbschmidt 2995235233Sbschmidt RAL_WRITE(sc, RT2860_TX_SW_CFG1, 0); 2996235233Sbschmidt if (sc->mac_rev < 0x0211) { 2997235233Sbschmidt RAL_WRITE(sc, RT2860_TX_SW_CFG2, 2998235233Sbschmidt sc->patch_dac ? 0x2c : 0x0f); 2999235233Sbschmidt } else 3000235233Sbschmidt RAL_WRITE(sc, RT2860_TX_SW_CFG2, 0); 3001235233Sbschmidt 3002235233Sbschmidt /* initialize RF registers from ROM */ 3003278551Skevlo if (sc->mac_ver < 0x5390) { 3004278551Skevlo for (i = 0; i < 10; i++) { 3005278551Skevlo if (sc->rf[i].reg == 0 || sc->rf[i].reg == 0xff) 3006278551Skevlo continue; 3007278551Skevlo rt3090_rf_write(sc, sc->rf[i].reg, sc->rf[i].val); 3008278551Skevlo } 3009235233Sbschmidt } 3010235233Sbschmidt} 3011235233Sbschmidt 3012235233Sbschmidtstatic void 3013235233Sbschmidtrt2860_set_leds(struct rt2860_softc *sc, uint16_t which) 3014235233Sbschmidt{ 3015235233Sbschmidt rt2860_mcu_cmd(sc, RT2860_MCU_CMD_LEDS, 3016235233Sbschmidt which | (sc->leds & 0x7f), 0); 3017235233Sbschmidt} 3018235233Sbschmidt 3019235233Sbschmidt/* 3020235233Sbschmidt * Hardware has a general-purpose programmable timer interrupt that can 3021235233Sbschmidt * periodically raise MAC_INT_4. 3022235233Sbschmidt */ 3023235233Sbschmidtstatic void 3024235233Sbschmidtrt2860_set_gp_timer(struct rt2860_softc *sc, int ms) 3025235233Sbschmidt{ 3026235233Sbschmidt uint32_t tmp; 3027235233Sbschmidt 3028235233Sbschmidt /* disable GP timer before reprogramming it */ 3029235233Sbschmidt tmp = RAL_READ(sc, RT2860_INT_TIMER_EN); 3030235233Sbschmidt RAL_WRITE(sc, RT2860_INT_TIMER_EN, tmp & ~RT2860_GP_TIMER_EN); 3031235233Sbschmidt 3032235233Sbschmidt if (ms == 0) 3033235233Sbschmidt return; 3034235233Sbschmidt 3035235233Sbschmidt tmp = RAL_READ(sc, RT2860_INT_TIMER_CFG); 3036235233Sbschmidt ms *= 16; /* Unit: 64us */ 3037235233Sbschmidt tmp = (tmp & 0xffff) | ms << RT2860_GP_TIMER_SHIFT; 3038235233Sbschmidt RAL_WRITE(sc, RT2860_INT_TIMER_CFG, tmp); 3039235233Sbschmidt 3040235233Sbschmidt /* enable GP timer */ 3041235233Sbschmidt tmp = RAL_READ(sc, RT2860_INT_TIMER_EN); 3042235233Sbschmidt RAL_WRITE(sc, RT2860_INT_TIMER_EN, tmp | RT2860_GP_TIMER_EN); 3043235233Sbschmidt} 3044235233Sbschmidt 3045235233Sbschmidtstatic void 3046235233Sbschmidtrt2860_set_bssid(struct rt2860_softc *sc, const uint8_t *bssid) 3047235233Sbschmidt{ 3048235233Sbschmidt RAL_WRITE(sc, RT2860_MAC_BSSID_DW0, 3049235233Sbschmidt bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24); 3050235233Sbschmidt RAL_WRITE(sc, RT2860_MAC_BSSID_DW1, 3051235233Sbschmidt bssid[4] | bssid[5] << 8); 3052235233Sbschmidt} 3053235233Sbschmidt 3054235233Sbschmidtstatic void 3055235233Sbschmidtrt2860_set_macaddr(struct rt2860_softc *sc, const uint8_t *addr) 3056235233Sbschmidt{ 3057235233Sbschmidt RAL_WRITE(sc, RT2860_MAC_ADDR_DW0, 3058235233Sbschmidt addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24); 3059235233Sbschmidt RAL_WRITE(sc, RT2860_MAC_ADDR_DW1, 3060235233Sbschmidt addr[4] | addr[5] << 8 | 0xff << 16); 3061235233Sbschmidt} 3062235233Sbschmidt 3063235233Sbschmidtstatic void 3064283540Sglebiusrt2860_updateslot(struct ieee80211com *ic) 3065235233Sbschmidt{ 3066283540Sglebius struct rt2860_softc *sc = ic->ic_softc; 3067235233Sbschmidt uint32_t tmp; 3068235233Sbschmidt 3069235233Sbschmidt tmp = RAL_READ(sc, RT2860_BKOFF_SLOT_CFG); 3070235233Sbschmidt tmp &= ~0xff; 3071292165Savos tmp |= IEEE80211_GET_SLOTTIME(ic); 3072235233Sbschmidt RAL_WRITE(sc, RT2860_BKOFF_SLOT_CFG, tmp); 3073235233Sbschmidt} 3074235233Sbschmidt 3075235233Sbschmidtstatic void 3076287197Sglebiusrt2860_updateprot(struct rt2860_softc *sc) 3077235233Sbschmidt{ 3078287197Sglebius struct ieee80211com *ic = &sc->sc_ic; 3079235233Sbschmidt uint32_t tmp; 3080235233Sbschmidt 3081235233Sbschmidt tmp = RT2860_RTSTH_EN | RT2860_PROT_NAV_SHORT | RT2860_TXOP_ALLOW_ALL; 3082235233Sbschmidt /* setup protection frame rate (MCS code) */ 3083235233Sbschmidt tmp |= IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ? 3084235233Sbschmidt rt2860_rates[RT2860_RIDX_OFDM6].mcs : 3085235233Sbschmidt rt2860_rates[RT2860_RIDX_CCK11].mcs; 3086235233Sbschmidt 3087235233Sbschmidt /* CCK frames don't require protection */ 3088235233Sbschmidt RAL_WRITE(sc, RT2860_CCK_PROT_CFG, tmp); 3089235233Sbschmidt 3090235233Sbschmidt if (ic->ic_flags & IEEE80211_F_USEPROT) { 3091235233Sbschmidt if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) 3092235233Sbschmidt tmp |= RT2860_PROT_CTRL_RTS_CTS; 3093235233Sbschmidt else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) 3094235233Sbschmidt tmp |= RT2860_PROT_CTRL_CTS; 3095235233Sbschmidt } 3096235233Sbschmidt RAL_WRITE(sc, RT2860_OFDM_PROT_CFG, tmp); 3097235233Sbschmidt} 3098235233Sbschmidt 3099235233Sbschmidtstatic void 3100283540Sglebiusrt2860_update_promisc(struct ieee80211com *ic) 3101235233Sbschmidt{ 3102283540Sglebius struct rt2860_softc *sc = ic->ic_softc; 3103235233Sbschmidt uint32_t tmp; 3104235233Sbschmidt 3105235233Sbschmidt tmp = RAL_READ(sc, RT2860_RX_FILTR_CFG); 3106235233Sbschmidt tmp &= ~RT2860_DROP_NOT_MYBSS; 3107287197Sglebius if (ic->ic_promisc == 0) 3108235233Sbschmidt tmp |= RT2860_DROP_NOT_MYBSS; 3109235233Sbschmidt RAL_WRITE(sc, RT2860_RX_FILTR_CFG, tmp); 3110235233Sbschmidt} 3111235233Sbschmidt 3112235233Sbschmidtstatic int 3113235233Sbschmidtrt2860_updateedca(struct ieee80211com *ic) 3114235233Sbschmidt{ 3115287197Sglebius struct rt2860_softc *sc = ic->ic_softc; 3116235233Sbschmidt const struct wmeParams *wmep; 3117235233Sbschmidt int aci; 3118235233Sbschmidt 3119235233Sbschmidt wmep = ic->ic_wme.wme_chanParams.cap_wmeParams; 3120235233Sbschmidt 3121235233Sbschmidt /* update MAC TX configuration registers */ 3122235233Sbschmidt for (aci = 0; aci < WME_NUM_AC; aci++) { 3123235233Sbschmidt RAL_WRITE(sc, RT2860_EDCA_AC_CFG(aci), 3124235233Sbschmidt wmep[aci].wmep_logcwmax << 16 | 3125235233Sbschmidt wmep[aci].wmep_logcwmin << 12 | 3126235233Sbschmidt wmep[aci].wmep_aifsn << 8 | 3127235233Sbschmidt wmep[aci].wmep_txopLimit); 3128235233Sbschmidt } 3129235233Sbschmidt 3130235233Sbschmidt /* update SCH/DMA registers too */ 3131235233Sbschmidt RAL_WRITE(sc, RT2860_WMM_AIFSN_CFG, 3132235233Sbschmidt wmep[WME_AC_VO].wmep_aifsn << 12 | 3133235233Sbschmidt wmep[WME_AC_VI].wmep_aifsn << 8 | 3134235233Sbschmidt wmep[WME_AC_BK].wmep_aifsn << 4 | 3135235233Sbschmidt wmep[WME_AC_BE].wmep_aifsn); 3136235233Sbschmidt RAL_WRITE(sc, RT2860_WMM_CWMIN_CFG, 3137235233Sbschmidt wmep[WME_AC_VO].wmep_logcwmin << 12 | 3138235233Sbschmidt wmep[WME_AC_VI].wmep_logcwmin << 8 | 3139235233Sbschmidt wmep[WME_AC_BK].wmep_logcwmin << 4 | 3140235233Sbschmidt wmep[WME_AC_BE].wmep_logcwmin); 3141235233Sbschmidt RAL_WRITE(sc, RT2860_WMM_CWMAX_CFG, 3142235233Sbschmidt wmep[WME_AC_VO].wmep_logcwmax << 12 | 3143235233Sbschmidt wmep[WME_AC_VI].wmep_logcwmax << 8 | 3144235233Sbschmidt wmep[WME_AC_BK].wmep_logcwmax << 4 | 3145235233Sbschmidt wmep[WME_AC_BE].wmep_logcwmax); 3146235233Sbschmidt RAL_WRITE(sc, RT2860_WMM_TXOP0_CFG, 3147235233Sbschmidt wmep[WME_AC_BK].wmep_txopLimit << 16 | 3148235233Sbschmidt wmep[WME_AC_BE].wmep_txopLimit); 3149235233Sbschmidt RAL_WRITE(sc, RT2860_WMM_TXOP1_CFG, 3150235233Sbschmidt wmep[WME_AC_VO].wmep_txopLimit << 16 | 3151235233Sbschmidt wmep[WME_AC_VI].wmep_txopLimit); 3152235233Sbschmidt 3153235233Sbschmidt return 0; 3154235233Sbschmidt} 3155235233Sbschmidt 3156235233Sbschmidt#ifdef HW_CRYPTO 3157235233Sbschmidtstatic int 3158235233Sbschmidtrt2860_set_key(struct ieee80211com *ic, struct ieee80211_node *ni, 3159235233Sbschmidt struct ieee80211_key *k) 3160235233Sbschmidt{ 3161235233Sbschmidt struct rt2860_softc *sc = ic->ic_softc; 3162235233Sbschmidt bus_size_t base; 3163235233Sbschmidt uint32_t attr; 3164235233Sbschmidt uint8_t mode, wcid, iv[8]; 3165235233Sbschmidt 3166235233Sbschmidt /* defer setting of WEP keys until interface is brought up */ 3167235233Sbschmidt if ((ic->ic_if.if_flags & (IFF_UP | IFF_RUNNING)) != 3168235233Sbschmidt (IFF_UP | IFF_RUNNING)) 3169235233Sbschmidt return 0; 3170235233Sbschmidt 3171235233Sbschmidt /* map net80211 cipher to RT2860 security mode */ 3172235233Sbschmidt switch (k->k_cipher) { 3173235233Sbschmidt case IEEE80211_CIPHER_WEP40: 3174235233Sbschmidt mode = RT2860_MODE_WEP40; 3175235233Sbschmidt break; 3176235233Sbschmidt case IEEE80211_CIPHER_WEP104: 3177235233Sbschmidt mode = RT2860_MODE_WEP104; 3178235233Sbschmidt break; 3179235233Sbschmidt case IEEE80211_CIPHER_TKIP: 3180235233Sbschmidt mode = RT2860_MODE_TKIP; 3181235233Sbschmidt break; 3182235233Sbschmidt case IEEE80211_CIPHER_CCMP: 3183235233Sbschmidt mode = RT2860_MODE_AES_CCMP; 3184235233Sbschmidt break; 3185235233Sbschmidt default: 3186235233Sbschmidt return EINVAL; 3187235233Sbschmidt } 3188235233Sbschmidt 3189235233Sbschmidt if (k->k_flags & IEEE80211_KEY_GROUP) { 3190235233Sbschmidt wcid = 0; /* NB: update WCID0 for group keys */ 3191235233Sbschmidt base = RT2860_SKEY(0, k->k_id); 3192235233Sbschmidt } else { 3193235233Sbschmidt wcid = ((struct rt2860_node *)ni)->wcid; 3194235233Sbschmidt base = RT2860_PKEY(wcid); 3195235233Sbschmidt } 3196235233Sbschmidt 3197235233Sbschmidt if (k->k_cipher == IEEE80211_CIPHER_TKIP) { 3198235233Sbschmidt RAL_WRITE_REGION_1(sc, base, k->k_key, 16); 3199235233Sbschmidt#ifndef IEEE80211_STA_ONLY 3200235233Sbschmidt if (ic->ic_opmode == IEEE80211_M_HOSTAP) { 3201235233Sbschmidt RAL_WRITE_REGION_1(sc, base + 16, &k->k_key[16], 8); 3202235233Sbschmidt RAL_WRITE_REGION_1(sc, base + 24, &k->k_key[24], 8); 3203235233Sbschmidt } else 3204235233Sbschmidt#endif 3205235233Sbschmidt { 3206235233Sbschmidt RAL_WRITE_REGION_1(sc, base + 16, &k->k_key[24], 8); 3207235233Sbschmidt RAL_WRITE_REGION_1(sc, base + 24, &k->k_key[16], 8); 3208235233Sbschmidt } 3209235233Sbschmidt } else 3210235233Sbschmidt RAL_WRITE_REGION_1(sc, base, k->k_key, k->k_len); 3211235233Sbschmidt 3212235233Sbschmidt if (!(k->k_flags & IEEE80211_KEY_GROUP) || 3213235233Sbschmidt (k->k_flags & IEEE80211_KEY_TX)) { 3214235233Sbschmidt /* set initial packet number in IV+EIV */ 3215235233Sbschmidt if (k->k_cipher == IEEE80211_CIPHER_WEP40 || 3216235233Sbschmidt k->k_cipher == IEEE80211_CIPHER_WEP104) { 3217235233Sbschmidt uint32_t val = arc4random(); 3218235233Sbschmidt /* skip weak IVs from Fluhrer/Mantin/Shamir */ 3219235233Sbschmidt if (val >= 0x03ff00 && (val & 0xf8ff00) == 0x00ff00) 3220235233Sbschmidt val += 0x000100; 3221235233Sbschmidt iv[0] = val; 3222235233Sbschmidt iv[1] = val >> 8; 3223235233Sbschmidt iv[2] = val >> 16; 3224235233Sbschmidt iv[3] = k->k_id << 6; 3225235233Sbschmidt iv[4] = iv[5] = iv[6] = iv[7] = 0; 3226235233Sbschmidt } else { 3227235233Sbschmidt if (k->k_cipher == IEEE80211_CIPHER_TKIP) { 3228235233Sbschmidt iv[0] = k->k_tsc >> 8; 3229235233Sbschmidt iv[1] = (iv[0] | 0x20) & 0x7f; 3230235233Sbschmidt iv[2] = k->k_tsc; 3231235233Sbschmidt } else /* CCMP */ { 3232235233Sbschmidt iv[0] = k->k_tsc; 3233235233Sbschmidt iv[1] = k->k_tsc >> 8; 3234235233Sbschmidt iv[2] = 0; 3235235233Sbschmidt } 3236235233Sbschmidt iv[3] = k->k_id << 6 | IEEE80211_WEP_EXTIV; 3237235233Sbschmidt iv[4] = k->k_tsc >> 16; 3238235233Sbschmidt iv[5] = k->k_tsc >> 24; 3239235233Sbschmidt iv[6] = k->k_tsc >> 32; 3240235233Sbschmidt iv[7] = k->k_tsc >> 40; 3241235233Sbschmidt } 3242235233Sbschmidt RAL_WRITE_REGION_1(sc, RT2860_IVEIV(wcid), iv, 8); 3243235233Sbschmidt } 3244235233Sbschmidt 3245235233Sbschmidt if (k->k_flags & IEEE80211_KEY_GROUP) { 3246235233Sbschmidt /* install group key */ 3247235233Sbschmidt attr = RAL_READ(sc, RT2860_SKEY_MODE_0_7); 3248235233Sbschmidt attr &= ~(0xf << (k->k_id * 4)); 3249235233Sbschmidt attr |= mode << (k->k_id * 4); 3250235233Sbschmidt RAL_WRITE(sc, RT2860_SKEY_MODE_0_7, attr); 3251235233Sbschmidt } else { 3252235233Sbschmidt /* install pairwise key */ 3253235233Sbschmidt attr = RAL_READ(sc, RT2860_WCID_ATTR(wcid)); 3254235233Sbschmidt attr = (attr & ~0xf) | (mode << 1) | RT2860_RX_PKEY_EN; 3255235233Sbschmidt RAL_WRITE(sc, RT2860_WCID_ATTR(wcid), attr); 3256235233Sbschmidt } 3257235233Sbschmidt return 0; 3258235233Sbschmidt} 3259235233Sbschmidt 3260235233Sbschmidtstatic void 3261235233Sbschmidtrt2860_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni, 3262235233Sbschmidt struct ieee80211_key *k) 3263235233Sbschmidt{ 3264235233Sbschmidt struct rt2860_softc *sc = ic->ic_softc; 3265235233Sbschmidt uint32_t attr; 3266235233Sbschmidt uint8_t wcid; 3267235233Sbschmidt 3268235233Sbschmidt if (k->k_flags & IEEE80211_KEY_GROUP) { 3269235233Sbschmidt /* remove group key */ 3270235233Sbschmidt attr = RAL_READ(sc, RT2860_SKEY_MODE_0_7); 3271235233Sbschmidt attr &= ~(0xf << (k->k_id * 4)); 3272235233Sbschmidt RAL_WRITE(sc, RT2860_SKEY_MODE_0_7, attr); 3273235233Sbschmidt 3274235233Sbschmidt } else { 3275235233Sbschmidt /* remove pairwise key */ 3276235233Sbschmidt wcid = ((struct rt2860_node *)ni)->wcid; 3277235233Sbschmidt attr = RAL_READ(sc, RT2860_WCID_ATTR(wcid)); 3278235233Sbschmidt attr &= ~0xf; 3279235233Sbschmidt RAL_WRITE(sc, RT2860_WCID_ATTR(wcid), attr); 3280235233Sbschmidt } 3281235233Sbschmidt} 3282235233Sbschmidt#endif 3283235233Sbschmidt 3284235233Sbschmidtstatic int8_t 3285235233Sbschmidtrt2860_rssi2dbm(struct rt2860_softc *sc, uint8_t rssi, uint8_t rxchain) 3286235233Sbschmidt{ 3287287197Sglebius struct ieee80211com *ic = &sc->sc_ic; 3288235233Sbschmidt struct ieee80211_channel *c = ic->ic_curchan; 3289235233Sbschmidt int delta; 3290235233Sbschmidt 3291235233Sbschmidt if (IEEE80211_IS_CHAN_5GHZ(c)) { 3292235233Sbschmidt u_int chan = ieee80211_chan2ieee(ic, c); 3293235233Sbschmidt delta = sc->rssi_5ghz[rxchain]; 3294235233Sbschmidt 3295235233Sbschmidt /* determine channel group */ 3296235233Sbschmidt if (chan <= 64) 3297235233Sbschmidt delta -= sc->lna[1]; 3298235233Sbschmidt else if (chan <= 128) 3299235233Sbschmidt delta -= sc->lna[2]; 3300235233Sbschmidt else 3301235233Sbschmidt delta -= sc->lna[3]; 3302235233Sbschmidt } else 3303235233Sbschmidt delta = sc->rssi_2ghz[rxchain] - sc->lna[0]; 3304235233Sbschmidt 3305235233Sbschmidt return -12 - delta - rssi; 3306235233Sbschmidt} 3307235233Sbschmidt 3308235233Sbschmidt/* 3309235233Sbschmidt * Add `delta' (signed) to each 4-bit sub-word of a 32-bit word. 3310235233Sbschmidt * Used to adjust per-rate Tx power registers. 3311235233Sbschmidt */ 3312235233Sbschmidtstatic __inline uint32_t 3313235233Sbschmidtb4inc(uint32_t b32, int8_t delta) 3314235233Sbschmidt{ 3315235233Sbschmidt int8_t i, b4; 3316235233Sbschmidt 3317235233Sbschmidt for (i = 0; i < 8; i++) { 3318235233Sbschmidt b4 = b32 & 0xf; 3319235233Sbschmidt b4 += delta; 3320235233Sbschmidt if (b4 < 0) 3321235233Sbschmidt b4 = 0; 3322235233Sbschmidt else if (b4 > 0xf) 3323235233Sbschmidt b4 = 0xf; 3324235233Sbschmidt b32 = b32 >> 4 | b4 << 28; 3325235233Sbschmidt } 3326235233Sbschmidt return b32; 3327235233Sbschmidt} 3328235233Sbschmidt 3329235233Sbschmidtstatic const char * 3330300006Skevlort2860_get_rf(uint16_t rev) 3331235233Sbschmidt{ 3332235233Sbschmidt switch (rev) { 3333235233Sbschmidt case RT2860_RF_2820: return "RT2820"; 3334235233Sbschmidt case RT2860_RF_2850: return "RT2850"; 3335235233Sbschmidt case RT2860_RF_2720: return "RT2720"; 3336235233Sbschmidt case RT2860_RF_2750: return "RT2750"; 3337235233Sbschmidt case RT3070_RF_3020: return "RT3020"; 3338235233Sbschmidt case RT3070_RF_2020: return "RT2020"; 3339235233Sbschmidt case RT3070_RF_3021: return "RT3021"; 3340235233Sbschmidt case RT3070_RF_3022: return "RT3022"; 3341235233Sbschmidt case RT3070_RF_3052: return "RT3052"; 3342235233Sbschmidt case RT3070_RF_3320: return "RT3320"; 3343235233Sbschmidt case RT3070_RF_3053: return "RT3053"; 3344300006Skevlo case RT5390_RF_5360: return "RT5360"; 3345278551Skevlo case RT5390_RF_5390: return "RT5390"; 3346235233Sbschmidt default: return "unknown"; 3347235233Sbschmidt } 3348235233Sbschmidt} 3349235233Sbschmidt 3350235233Sbschmidtstatic int 3351235233Sbschmidtrt2860_read_eeprom(struct rt2860_softc *sc, uint8_t macaddr[IEEE80211_ADDR_LEN]) 3352235233Sbschmidt{ 3353235233Sbschmidt int8_t delta_2ghz, delta_5ghz; 3354235233Sbschmidt uint32_t tmp; 3355235233Sbschmidt uint16_t val; 3356235233Sbschmidt int ridx, ant, i; 3357235233Sbschmidt 3358235233Sbschmidt /* check whether the ROM is eFUSE ROM or EEPROM */ 3359235233Sbschmidt sc->sc_srom_read = rt2860_eeprom_read_2; 3360235233Sbschmidt if (sc->mac_ver >= 0x3071) { 3361235233Sbschmidt tmp = RAL_READ(sc, RT3070_EFUSE_CTRL); 3362235233Sbschmidt DPRINTF(("EFUSE_CTRL=0x%08x\n", tmp)); 3363235233Sbschmidt if (tmp & RT3070_SEL_EFUSE) 3364235233Sbschmidt sc->sc_srom_read = rt3090_efuse_read_2; 3365235233Sbschmidt } 3366235233Sbschmidt 3367300006Skevlo#ifdef RAL_DEBUG 3368235233Sbschmidt /* read EEPROM version */ 3369235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_VERSION); 3370287853Skevlo DPRINTF(("EEPROM rev=%d, FAE=%d\n", val >> 8, val & 0xff)); 3371300006Skevlo#endif 3372235233Sbschmidt 3373235233Sbschmidt /* read MAC address */ 3374235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_MAC01); 3375235233Sbschmidt macaddr[0] = val & 0xff; 3376235233Sbschmidt macaddr[1] = val >> 8; 3377235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_MAC23); 3378235233Sbschmidt macaddr[2] = val & 0xff; 3379235233Sbschmidt macaddr[3] = val >> 8; 3380235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_MAC45); 3381235233Sbschmidt macaddr[4] = val & 0xff; 3382235233Sbschmidt macaddr[5] = val >> 8; 3383235233Sbschmidt 3384300006Skevlo#ifdef RAL_DEBUG 3385235233Sbschmidt /* read country code */ 3386235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_COUNTRY); 3387235233Sbschmidt DPRINTF(("EEPROM region code=0x%04x\n", val)); 3388300006Skevlo#endif 3389235233Sbschmidt 3390235233Sbschmidt /* read vendor BBP settings */ 3391235233Sbschmidt for (i = 0; i < 8; i++) { 3392235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_BBP_BASE + i); 3393235233Sbschmidt sc->bbp[i].val = val & 0xff; 3394235233Sbschmidt sc->bbp[i].reg = val >> 8; 3395235233Sbschmidt DPRINTF(("BBP%d=0x%02x\n", sc->bbp[i].reg, sc->bbp[i].val)); 3396235233Sbschmidt } 3397235233Sbschmidt if (sc->mac_ver >= 0x3071) { 3398235233Sbschmidt /* read vendor RF settings */ 3399235233Sbschmidt for (i = 0; i < 10; i++) { 3400235233Sbschmidt val = rt2860_srom_read(sc, RT3071_EEPROM_RF_BASE + i); 3401235233Sbschmidt sc->rf[i].val = val & 0xff; 3402235233Sbschmidt sc->rf[i].reg = val >> 8; 3403235233Sbschmidt DPRINTF(("RF%d=0x%02x\n", sc->rf[i].reg, 3404235233Sbschmidt sc->rf[i].val)); 3405235233Sbschmidt } 3406235233Sbschmidt } 3407235233Sbschmidt 3408235233Sbschmidt /* read RF frequency offset from EEPROM */ 3409235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_FREQ_LEDS); 3410235233Sbschmidt sc->freq = ((val & 0xff) != 0xff) ? val & 0xff : 0; 3411235233Sbschmidt DPRINTF(("EEPROM freq offset %d\n", sc->freq & 0xff)); 3412235233Sbschmidt if ((val >> 8) != 0xff) { 3413235233Sbschmidt /* read LEDs operating mode */ 3414235233Sbschmidt sc->leds = val >> 8; 3415235233Sbschmidt sc->led[0] = rt2860_srom_read(sc, RT2860_EEPROM_LED1); 3416235233Sbschmidt sc->led[1] = rt2860_srom_read(sc, RT2860_EEPROM_LED2); 3417235233Sbschmidt sc->led[2] = rt2860_srom_read(sc, RT2860_EEPROM_LED3); 3418235233Sbschmidt } else { 3419235233Sbschmidt /* broken EEPROM, use default settings */ 3420235233Sbschmidt sc->leds = 0x01; 3421235233Sbschmidt sc->led[0] = 0x5555; 3422235233Sbschmidt sc->led[1] = 0x2221; 3423235233Sbschmidt sc->led[2] = 0xa9f8; 3424235233Sbschmidt } 3425235233Sbschmidt DPRINTF(("EEPROM LED mode=0x%02x, LEDs=0x%04x/0x%04x/0x%04x\n", 3426235233Sbschmidt sc->leds, sc->led[0], sc->led[1], sc->led[2])); 3427235233Sbschmidt 3428235233Sbschmidt /* read RF information */ 3429235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_ANTENNA); 3430300006Skevlo if (sc->mac_ver >= 0x5390) 3431300006Skevlo sc->rf_rev = rt2860_srom_read(sc, RT2860_EEPROM_CHIPID); 3432300006Skevlo else 3433235233Sbschmidt sc->rf_rev = (val >> 8) & 0xf; 3434300006Skevlo sc->ntxchains = (val >> 4) & 0xf; 3435300006Skevlo sc->nrxchains = val & 0xf; 3436235233Sbschmidt DPRINTF(("EEPROM RF rev=0x%02x chains=%dT%dR\n", 3437235233Sbschmidt sc->rf_rev, sc->ntxchains, sc->nrxchains)); 3438235233Sbschmidt 3439235233Sbschmidt /* check if RF supports automatic Tx access gain control */ 3440235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_CONFIG); 3441235233Sbschmidt DPRINTF(("EEPROM CFG 0x%04x\n", val)); 3442235233Sbschmidt /* check if driver should patch the DAC issue */ 3443235233Sbschmidt if ((val >> 8) != 0xff) 3444235233Sbschmidt sc->patch_dac = (val >> 15) & 1; 3445235233Sbschmidt if ((val & 0xff) != 0xff) { 3446235233Sbschmidt sc->ext_5ghz_lna = (val >> 3) & 1; 3447235233Sbschmidt sc->ext_2ghz_lna = (val >> 2) & 1; 3448235233Sbschmidt /* check if RF supports automatic Tx access gain control */ 3449297793Spfg sc->calib_2ghz = sc->calib_5ghz = 0; /* XXX (val >> 1) & 1 */ 3450235233Sbschmidt /* check if we have a hardware radio switch */ 3451235233Sbschmidt sc->rfswitch = val & 1; 3452235233Sbschmidt } 3453235233Sbschmidt if (sc->sc_flags & RT2860_ADVANCED_PS) { 3454235233Sbschmidt /* read PCIe power save level */ 3455235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_PCIE_PSLEVEL); 3456235233Sbschmidt if ((val & 0xff) != 0xff) { 3457235233Sbschmidt sc->pslevel = val & 0x3; 3458235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_REV); 3459235233Sbschmidt if ((val & 0xff80) != 0x9280) 3460235233Sbschmidt sc->pslevel = MIN(sc->pslevel, 1); 3461235233Sbschmidt DPRINTF(("EEPROM PCIe PS Level=%d\n", sc->pslevel)); 3462235233Sbschmidt } 3463235233Sbschmidt } 3464235233Sbschmidt 3465235233Sbschmidt /* read power settings for 2GHz channels */ 3466235233Sbschmidt for (i = 0; i < 14; i += 2) { 3467235233Sbschmidt val = rt2860_srom_read(sc, 3468235233Sbschmidt RT2860_EEPROM_PWR2GHZ_BASE1 + i / 2); 3469235233Sbschmidt sc->txpow1[i + 0] = (int8_t)(val & 0xff); 3470235233Sbschmidt sc->txpow1[i + 1] = (int8_t)(val >> 8); 3471235233Sbschmidt 3472278551Skevlo if (sc->mac_ver != 0x5390) { 3473278551Skevlo val = rt2860_srom_read(sc, 3474278551Skevlo RT2860_EEPROM_PWR2GHZ_BASE2 + i / 2); 3475278551Skevlo sc->txpow2[i + 0] = (int8_t)(val & 0xff); 3476278551Skevlo sc->txpow2[i + 1] = (int8_t)(val >> 8); 3477278551Skevlo } 3478235233Sbschmidt } 3479235233Sbschmidt /* fix broken Tx power entries */ 3480235233Sbschmidt for (i = 0; i < 14; i++) { 3481278551Skevlo if (sc->txpow1[i] < 0 || 3482278551Skevlo sc->txpow1[i] > ((sc->mac_ver >= 0x5390) ? 39 : 31)) 3483235233Sbschmidt sc->txpow1[i] = 5; 3484278551Skevlo if (sc->mac_ver != 0x5390) { 3485278551Skevlo if (sc->txpow2[i] < 0 || 3486278551Skevlo sc->txpow2[i] > ((sc->mac_ver == 0x5392) ? 39 : 31)) 3487278551Skevlo sc->txpow2[i] = 5; 3488278551Skevlo } 3489235233Sbschmidt DPRINTF(("chan %d: power1=%d, power2=%d\n", 3490235233Sbschmidt rt2860_rf2850[i].chan, sc->txpow1[i], sc->txpow2[i])); 3491235233Sbschmidt } 3492235233Sbschmidt /* read power settings for 5GHz channels */ 3493235233Sbschmidt for (i = 0; i < 40; i += 2) { 3494235233Sbschmidt val = rt2860_srom_read(sc, 3495235233Sbschmidt RT2860_EEPROM_PWR5GHZ_BASE1 + i / 2); 3496235233Sbschmidt sc->txpow1[i + 14] = (int8_t)(val & 0xff); 3497235233Sbschmidt sc->txpow1[i + 15] = (int8_t)(val >> 8); 3498235233Sbschmidt 3499235233Sbschmidt val = rt2860_srom_read(sc, 3500235233Sbschmidt RT2860_EEPROM_PWR5GHZ_BASE2 + i / 2); 3501235233Sbschmidt sc->txpow2[i + 14] = (int8_t)(val & 0xff); 3502235233Sbschmidt sc->txpow2[i + 15] = (int8_t)(val >> 8); 3503235233Sbschmidt } 3504235233Sbschmidt /* fix broken Tx power entries */ 3505235233Sbschmidt for (i = 0; i < 40; i++) { 3506235233Sbschmidt if (sc->txpow1[14 + i] < -7 || sc->txpow1[14 + i] > 15) 3507235233Sbschmidt sc->txpow1[14 + i] = 5; 3508235233Sbschmidt if (sc->txpow2[14 + i] < -7 || sc->txpow2[14 + i] > 15) 3509235233Sbschmidt sc->txpow2[14 + i] = 5; 3510235233Sbschmidt DPRINTF(("chan %d: power1=%d, power2=%d\n", 3511235233Sbschmidt rt2860_rf2850[14 + i].chan, sc->txpow1[14 + i], 3512235233Sbschmidt sc->txpow2[14 + i])); 3513235233Sbschmidt } 3514235233Sbschmidt 3515235233Sbschmidt /* read Tx power compensation for each Tx rate */ 3516235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_DELTAPWR); 3517235233Sbschmidt delta_2ghz = delta_5ghz = 0; 3518235233Sbschmidt if ((val & 0xff) != 0xff && (val & 0x80)) { 3519235233Sbschmidt delta_2ghz = val & 0xf; 3520235233Sbschmidt if (!(val & 0x40)) /* negative number */ 3521235233Sbschmidt delta_2ghz = -delta_2ghz; 3522235233Sbschmidt } 3523235233Sbschmidt val >>= 8; 3524235233Sbschmidt if ((val & 0xff) != 0xff && (val & 0x80)) { 3525235233Sbschmidt delta_5ghz = val & 0xf; 3526235233Sbschmidt if (!(val & 0x40)) /* negative number */ 3527235233Sbschmidt delta_5ghz = -delta_5ghz; 3528235233Sbschmidt } 3529235233Sbschmidt DPRINTF(("power compensation=%d (2GHz), %d (5GHz)\n", 3530235233Sbschmidt delta_2ghz, delta_5ghz)); 3531235233Sbschmidt 3532235233Sbschmidt for (ridx = 0; ridx < 5; ridx++) { 3533235233Sbschmidt uint32_t reg; 3534235233Sbschmidt 3535235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_RPWR + ridx * 2); 3536235233Sbschmidt reg = val; 3537235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_RPWR + ridx * 2 + 1); 3538235233Sbschmidt reg |= (uint32_t)val << 16; 3539235233Sbschmidt 3540235233Sbschmidt sc->txpow20mhz[ridx] = reg; 3541235233Sbschmidt sc->txpow40mhz_2ghz[ridx] = b4inc(reg, delta_2ghz); 3542235233Sbschmidt sc->txpow40mhz_5ghz[ridx] = b4inc(reg, delta_5ghz); 3543235233Sbschmidt 3544235233Sbschmidt DPRINTF(("ridx %d: power 20MHz=0x%08x, 40MHz/2GHz=0x%08x, " 3545235233Sbschmidt "40MHz/5GHz=0x%08x\n", ridx, sc->txpow20mhz[ridx], 3546235233Sbschmidt sc->txpow40mhz_2ghz[ridx], sc->txpow40mhz_5ghz[ridx])); 3547235233Sbschmidt } 3548235233Sbschmidt 3549235233Sbschmidt /* read factory-calibrated samples for temperature compensation */ 3550235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI1_2GHZ); 3551235233Sbschmidt sc->tssi_2ghz[0] = val & 0xff; /* [-4] */ 3552235233Sbschmidt sc->tssi_2ghz[1] = val >> 8; /* [-3] */ 3553235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI2_2GHZ); 3554235233Sbschmidt sc->tssi_2ghz[2] = val & 0xff; /* [-2] */ 3555235233Sbschmidt sc->tssi_2ghz[3] = val >> 8; /* [-1] */ 3556235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI3_2GHZ); 3557235233Sbschmidt sc->tssi_2ghz[4] = val & 0xff; /* [+0] */ 3558235233Sbschmidt sc->tssi_2ghz[5] = val >> 8; /* [+1] */ 3559235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI4_2GHZ); 3560235233Sbschmidt sc->tssi_2ghz[6] = val & 0xff; /* [+2] */ 3561235233Sbschmidt sc->tssi_2ghz[7] = val >> 8; /* [+3] */ 3562235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI5_2GHZ); 3563235233Sbschmidt sc->tssi_2ghz[8] = val & 0xff; /* [+4] */ 3564235233Sbschmidt sc->step_2ghz = val >> 8; 3565235233Sbschmidt DPRINTF(("TSSI 2GHz: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x " 3566235233Sbschmidt "0x%02x 0x%02x step=%d\n", sc->tssi_2ghz[0], sc->tssi_2ghz[1], 3567235233Sbschmidt sc->tssi_2ghz[2], sc->tssi_2ghz[3], sc->tssi_2ghz[4], 3568235233Sbschmidt sc->tssi_2ghz[5], sc->tssi_2ghz[6], sc->tssi_2ghz[7], 3569235233Sbschmidt sc->tssi_2ghz[8], sc->step_2ghz)); 3570235233Sbschmidt /* check that ref value is correct, otherwise disable calibration */ 3571235233Sbschmidt if (sc->tssi_2ghz[4] == 0xff) 3572235233Sbschmidt sc->calib_2ghz = 0; 3573235233Sbschmidt 3574235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI1_5GHZ); 3575235233Sbschmidt sc->tssi_5ghz[0] = val & 0xff; /* [-4] */ 3576235233Sbschmidt sc->tssi_5ghz[1] = val >> 8; /* [-3] */ 3577235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI2_5GHZ); 3578235233Sbschmidt sc->tssi_5ghz[2] = val & 0xff; /* [-2] */ 3579235233Sbschmidt sc->tssi_5ghz[3] = val >> 8; /* [-1] */ 3580235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI3_5GHZ); 3581235233Sbschmidt sc->tssi_5ghz[4] = val & 0xff; /* [+0] */ 3582235233Sbschmidt sc->tssi_5ghz[5] = val >> 8; /* [+1] */ 3583235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI4_5GHZ); 3584235233Sbschmidt sc->tssi_5ghz[6] = val & 0xff; /* [+2] */ 3585235233Sbschmidt sc->tssi_5ghz[7] = val >> 8; /* [+3] */ 3586235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI5_5GHZ); 3587235233Sbschmidt sc->tssi_5ghz[8] = val & 0xff; /* [+4] */ 3588235233Sbschmidt sc->step_5ghz = val >> 8; 3589235233Sbschmidt DPRINTF(("TSSI 5GHz: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x " 3590235233Sbschmidt "0x%02x 0x%02x step=%d\n", sc->tssi_5ghz[0], sc->tssi_5ghz[1], 3591235233Sbschmidt sc->tssi_5ghz[2], sc->tssi_5ghz[3], sc->tssi_5ghz[4], 3592235233Sbschmidt sc->tssi_5ghz[5], sc->tssi_5ghz[6], sc->tssi_5ghz[7], 3593235233Sbschmidt sc->tssi_5ghz[8], sc->step_5ghz)); 3594235233Sbschmidt /* check that ref value is correct, otherwise disable calibration */ 3595235233Sbschmidt if (sc->tssi_5ghz[4] == 0xff) 3596235233Sbschmidt sc->calib_5ghz = 0; 3597235233Sbschmidt 3598235233Sbschmidt /* read RSSI offsets and LNA gains from EEPROM */ 3599235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_RSSI1_2GHZ); 3600235233Sbschmidt sc->rssi_2ghz[0] = val & 0xff; /* Ant A */ 3601235233Sbschmidt sc->rssi_2ghz[1] = val >> 8; /* Ant B */ 3602235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_RSSI2_2GHZ); 3603235233Sbschmidt if (sc->mac_ver >= 0x3071) { 3604235233Sbschmidt /* 3605235233Sbschmidt * On RT3090 chips (limited to 2 Rx chains), this ROM 3606235233Sbschmidt * field contains the Tx mixer gain for the 2GHz band. 3607235233Sbschmidt */ 3608235233Sbschmidt if ((val & 0xff) != 0xff) 3609235233Sbschmidt sc->txmixgain_2ghz = val & 0x7; 3610235233Sbschmidt DPRINTF(("tx mixer gain=%u (2GHz)\n", sc->txmixgain_2ghz)); 3611235233Sbschmidt } else 3612235233Sbschmidt sc->rssi_2ghz[2] = val & 0xff; /* Ant C */ 3613235233Sbschmidt sc->lna[2] = val >> 8; /* channel group 2 */ 3614235233Sbschmidt 3615235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_RSSI1_5GHZ); 3616235233Sbschmidt sc->rssi_5ghz[0] = val & 0xff; /* Ant A */ 3617235233Sbschmidt sc->rssi_5ghz[1] = val >> 8; /* Ant B */ 3618235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_RSSI2_5GHZ); 3619235233Sbschmidt sc->rssi_5ghz[2] = val & 0xff; /* Ant C */ 3620235233Sbschmidt sc->lna[3] = val >> 8; /* channel group 3 */ 3621235233Sbschmidt 3622235233Sbschmidt val = rt2860_srom_read(sc, RT2860_EEPROM_LNA); 3623235233Sbschmidt if (sc->mac_ver >= 0x3071) 3624235233Sbschmidt sc->lna[0] = RT3090_DEF_LNA; 3625235233Sbschmidt else /* channel group 0 */ 3626235233Sbschmidt sc->lna[0] = val & 0xff; 3627235233Sbschmidt sc->lna[1] = val >> 8; /* channel group 1 */ 3628235233Sbschmidt 3629235233Sbschmidt /* fix broken 5GHz LNA entries */ 3630235233Sbschmidt if (sc->lna[2] == 0 || sc->lna[2] == 0xff) { 3631235233Sbschmidt DPRINTF(("invalid LNA for channel group %d\n", 2)); 3632235233Sbschmidt sc->lna[2] = sc->lna[1]; 3633235233Sbschmidt } 3634235233Sbschmidt if (sc->lna[3] == 0 || sc->lna[3] == 0xff) { 3635235233Sbschmidt DPRINTF(("invalid LNA for channel group %d\n", 3)); 3636235233Sbschmidt sc->lna[3] = sc->lna[1]; 3637235233Sbschmidt } 3638235233Sbschmidt 3639235233Sbschmidt /* fix broken RSSI offset entries */ 3640235233Sbschmidt for (ant = 0; ant < 3; ant++) { 3641235233Sbschmidt if (sc->rssi_2ghz[ant] < -10 || sc->rssi_2ghz[ant] > 10) { 3642235233Sbschmidt DPRINTF(("invalid RSSI%d offset: %d (2GHz)\n", 3643235233Sbschmidt ant + 1, sc->rssi_2ghz[ant])); 3644235233Sbschmidt sc->rssi_2ghz[ant] = 0; 3645235233Sbschmidt } 3646235233Sbschmidt if (sc->rssi_5ghz[ant] < -10 || sc->rssi_5ghz[ant] > 10) { 3647235233Sbschmidt DPRINTF(("invalid RSSI%d offset: %d (5GHz)\n", 3648235233Sbschmidt ant + 1, sc->rssi_5ghz[ant])); 3649235233Sbschmidt sc->rssi_5ghz[ant] = 0; 3650235233Sbschmidt } 3651235233Sbschmidt } 3652235233Sbschmidt 3653235233Sbschmidt return 0; 3654235233Sbschmidt} 3655235233Sbschmidt 3656278551Skevlostatic int 3657235233Sbschmidtrt2860_bbp_init(struct rt2860_softc *sc) 3658235233Sbschmidt{ 3659235233Sbschmidt int i, ntries; 3660235233Sbschmidt 3661235233Sbschmidt /* wait for BBP to wake up */ 3662235233Sbschmidt for (ntries = 0; ntries < 20; ntries++) { 3663235233Sbschmidt uint8_t bbp0 = rt2860_mcu_bbp_read(sc, 0); 3664235233Sbschmidt if (bbp0 != 0 && bbp0 != 0xff) 3665235233Sbschmidt break; 3666235233Sbschmidt } 3667235233Sbschmidt if (ntries == 20) { 3668235233Sbschmidt device_printf(sc->sc_dev, 3669235233Sbschmidt "timeout waiting for BBP to wake up\n"); 3670278551Skevlo return (ETIMEDOUT); 3671235233Sbschmidt } 3672235233Sbschmidt 3673235233Sbschmidt /* initialize BBP registers to default values */ 3674278551Skevlo if (sc->mac_ver >= 0x5390) 3675278551Skevlo rt5390_bbp_init(sc); 3676278551Skevlo else { 3677278551Skevlo for (i = 0; i < nitems(rt2860_def_bbp); i++) { 3678278551Skevlo rt2860_mcu_bbp_write(sc, rt2860_def_bbp[i].reg, 3679278551Skevlo rt2860_def_bbp[i].val); 3680278551Skevlo } 3681235233Sbschmidt } 3682235233Sbschmidt 3683235233Sbschmidt /* fix BBP84 for RT2860E */ 3684235233Sbschmidt if (sc->mac_ver == 0x2860 && sc->mac_rev != 0x0101) 3685235233Sbschmidt rt2860_mcu_bbp_write(sc, 84, 0x19); 3686235233Sbschmidt 3687235233Sbschmidt if (sc->mac_ver >= 0x3071) { 3688235233Sbschmidt rt2860_mcu_bbp_write(sc, 79, 0x13); 3689235233Sbschmidt rt2860_mcu_bbp_write(sc, 80, 0x05); 3690235233Sbschmidt rt2860_mcu_bbp_write(sc, 81, 0x33); 3691235233Sbschmidt } else if (sc->mac_ver == 0x2860 && sc->mac_rev == 0x0100) { 3692235233Sbschmidt rt2860_mcu_bbp_write(sc, 69, 0x16); 3693235233Sbschmidt rt2860_mcu_bbp_write(sc, 73, 0x12); 3694235233Sbschmidt } 3695235233Sbschmidt 3696235233Sbschmidt return 0; 3697235233Sbschmidt} 3698235233Sbschmidt 3699278551Skevlostatic void 3700278551Skevlort5390_bbp_init(struct rt2860_softc *sc) 3701278551Skevlo{ 3702278551Skevlo uint8_t bbp; 3703278551Skevlo int i; 3704278551Skevlo 3705278551Skevlo /* Apply maximum likelihood detection for 2 stream case. */ 3706278551Skevlo if (sc->nrxchains > 1) { 3707278551Skevlo bbp = rt2860_mcu_bbp_read(sc, 105); 3708278551Skevlo rt2860_mcu_bbp_write(sc, 105, bbp | RT5390_MLD); 3709278551Skevlo } 3710278551Skevlo 3711278551Skevlo /* Avoid data lost and CRC error. */ 3712278551Skevlo bbp = rt2860_mcu_bbp_read(sc, 4); 3713278551Skevlo rt2860_mcu_bbp_write(sc, 4, bbp | RT5390_MAC_IF_CTRL); 3714278551Skevlo 3715278551Skevlo for (i = 0; i < nitems(rt5390_def_bbp); i++) { 3716278551Skevlo rt2860_mcu_bbp_write(sc, rt5390_def_bbp[i].reg, 3717278551Skevlo rt5390_def_bbp[i].val); 3718278551Skevlo } 3719278551Skevlo 3720278551Skevlo if (sc->mac_ver == 0x5392) { 3721278551Skevlo rt2860_mcu_bbp_write(sc, 84, 0x9a); 3722278551Skevlo rt2860_mcu_bbp_write(sc, 95, 0x9a); 3723278551Skevlo rt2860_mcu_bbp_write(sc, 98, 0x12); 3724278551Skevlo rt2860_mcu_bbp_write(sc, 106, 0x05); 3725278551Skevlo rt2860_mcu_bbp_write(sc, 134, 0xd0); 3726278551Skevlo rt2860_mcu_bbp_write(sc, 135, 0xf6); 3727278551Skevlo } 3728278551Skevlo 3729278551Skevlo bbp = rt2860_mcu_bbp_read(sc, 152); 3730278551Skevlo rt2860_mcu_bbp_write(sc, 152, bbp | 0x80); 3731278551Skevlo 3732278551Skevlo /* Disable hardware antenna diversity. */ 3733278551Skevlo if (sc->mac_ver == 0x5390) 3734278551Skevlo rt2860_mcu_bbp_write(sc, 154, 0); 3735278551Skevlo} 3736278551Skevlo 3737235233Sbschmidtstatic int 3738235233Sbschmidtrt2860_txrx_enable(struct rt2860_softc *sc) 3739235233Sbschmidt{ 3740287197Sglebius struct ieee80211com *ic = &sc->sc_ic; 3741235233Sbschmidt uint32_t tmp; 3742235233Sbschmidt int ntries; 3743235233Sbschmidt 3744235233Sbschmidt /* enable Tx/Rx DMA engine */ 3745235233Sbschmidt RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, RT2860_MAC_TX_EN); 3746235233Sbschmidt RAL_BARRIER_READ_WRITE(sc); 3747235233Sbschmidt for (ntries = 0; ntries < 200; ntries++) { 3748235233Sbschmidt tmp = RAL_READ(sc, RT2860_WPDMA_GLO_CFG); 3749235233Sbschmidt if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0) 3750235233Sbschmidt break; 3751235233Sbschmidt DELAY(1000); 3752235233Sbschmidt } 3753235233Sbschmidt if (ntries == 200) { 3754235233Sbschmidt device_printf(sc->sc_dev, "timeout waiting for DMA engine\n"); 3755235233Sbschmidt return ETIMEDOUT; 3756235233Sbschmidt } 3757235233Sbschmidt 3758235233Sbschmidt DELAY(50); 3759235233Sbschmidt 3760235233Sbschmidt tmp |= RT2860_RX_DMA_EN | RT2860_TX_DMA_EN | 3761235233Sbschmidt RT2860_WPDMA_BT_SIZE64 << RT2860_WPDMA_BT_SIZE_SHIFT; 3762235233Sbschmidt RAL_WRITE(sc, RT2860_WPDMA_GLO_CFG, tmp); 3763235233Sbschmidt 3764235233Sbschmidt /* set Rx filter */ 3765235233Sbschmidt tmp = RT2860_DROP_CRC_ERR | RT2860_DROP_PHY_ERR; 3766235233Sbschmidt if (ic->ic_opmode != IEEE80211_M_MONITOR) { 3767235233Sbschmidt tmp |= RT2860_DROP_UC_NOME | RT2860_DROP_DUPL | 3768235233Sbschmidt RT2860_DROP_CTS | RT2860_DROP_BA | RT2860_DROP_ACK | 3769235233Sbschmidt RT2860_DROP_VER_ERR | RT2860_DROP_CTRL_RSV | 3770235233Sbschmidt RT2860_DROP_CFACK | RT2860_DROP_CFEND; 3771235233Sbschmidt if (ic->ic_opmode == IEEE80211_M_STA) 3772235233Sbschmidt tmp |= RT2860_DROP_RTS | RT2860_DROP_PSPOLL; 3773235233Sbschmidt } 3774235233Sbschmidt RAL_WRITE(sc, RT2860_RX_FILTR_CFG, tmp); 3775235233Sbschmidt 3776235233Sbschmidt RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, 3777235233Sbschmidt RT2860_MAC_RX_EN | RT2860_MAC_TX_EN); 3778235233Sbschmidt 3779235233Sbschmidt return 0; 3780235233Sbschmidt} 3781235233Sbschmidt 3782235233Sbschmidtstatic void 3783235233Sbschmidtrt2860_init(void *arg) 3784235233Sbschmidt{ 3785235233Sbschmidt struct rt2860_softc *sc = arg; 3786287197Sglebius struct ieee80211com *ic = &sc->sc_ic; 3787235233Sbschmidt 3788235233Sbschmidt RAL_LOCK(sc); 3789235233Sbschmidt rt2860_init_locked(sc); 3790235233Sbschmidt RAL_UNLOCK(sc); 3791235233Sbschmidt 3792290133Skevlo if (sc->sc_flags & RT2860_RUNNING) 3793235233Sbschmidt ieee80211_start_all(ic); 3794235233Sbschmidt} 3795235233Sbschmidt 3796235233Sbschmidtstatic void 3797235233Sbschmidtrt2860_init_locked(struct rt2860_softc *sc) 3798235233Sbschmidt{ 3799287197Sglebius struct ieee80211com *ic = &sc->sc_ic; 3800287197Sglebius struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); 3801235233Sbschmidt uint32_t tmp; 3802235233Sbschmidt uint8_t bbp1, bbp3; 3803235233Sbschmidt int i, qid, ridx, ntries, error; 3804235233Sbschmidt 3805235233Sbschmidt RAL_LOCK_ASSERT(sc); 3806235233Sbschmidt 3807235233Sbschmidt if (sc->rfswitch) { 3808235233Sbschmidt /* hardware has a radio switch on GPIO pin 2 */ 3809235233Sbschmidt if (!(RAL_READ(sc, RT2860_GPIO_CTRL) & (1 << 2))) { 3810235233Sbschmidt device_printf(sc->sc_dev, 3811235233Sbschmidt "radio is disabled by hardware switch\n"); 3812235233Sbschmidt#ifdef notyet 3813235233Sbschmidt rt2860_stop_locked(sc); 3814235233Sbschmidt return; 3815235233Sbschmidt#endif 3816235233Sbschmidt } 3817235233Sbschmidt } 3818235233Sbschmidt RAL_WRITE(sc, RT2860_PWR_PIN_CFG, RT2860_IO_RA_PE); 3819235233Sbschmidt 3820235233Sbschmidt /* disable DMA */ 3821235233Sbschmidt tmp = RAL_READ(sc, RT2860_WPDMA_GLO_CFG); 3822301575Skevlo tmp &= ~(RT2860_RX_DMA_BUSY | RT2860_RX_DMA_EN | RT2860_TX_DMA_BUSY | 3823301575Skevlo RT2860_TX_DMA_EN); 3824301575Skevlo tmp |= RT2860_TX_WB_DDONE; 3825235233Sbschmidt RAL_WRITE(sc, RT2860_WPDMA_GLO_CFG, tmp); 3826235233Sbschmidt 3827301575Skevlo /* reset DMA indexes */ 3828301575Skevlo RAL_WRITE(sc, RT2860_WPDMA_RST_IDX, RT2860_RST_DRX_IDX0 | 3829301575Skevlo RT2860_RST_DTX_IDX5 | RT2860_RST_DTX_IDX4 | RT2860_RST_DTX_IDX3 | 3830301575Skevlo RT2860_RST_DTX_IDX2 | RT2860_RST_DTX_IDX1 | RT2860_RST_DTX_IDX0); 3831301575Skevlo 3832235233Sbschmidt /* PBF hardware reset */ 3833235233Sbschmidt RAL_WRITE(sc, RT2860_SYS_CTRL, 0xe1f); 3834235233Sbschmidt RAL_BARRIER_WRITE(sc); 3835235233Sbschmidt RAL_WRITE(sc, RT2860_SYS_CTRL, 0xe00); 3836235233Sbschmidt 3837235233Sbschmidt if ((error = rt2860_load_microcode(sc)) != 0) { 3838235233Sbschmidt device_printf(sc->sc_dev, "could not load 8051 microcode\n"); 3839235233Sbschmidt rt2860_stop_locked(sc); 3840235233Sbschmidt return; 3841235233Sbschmidt } 3842235233Sbschmidt 3843287197Sglebius rt2860_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr); 3844235233Sbschmidt 3845235233Sbschmidt /* init Tx power for all Tx rates (from EEPROM) */ 3846235233Sbschmidt for (ridx = 0; ridx < 5; ridx++) { 3847235233Sbschmidt if (sc->txpow20mhz[ridx] == 0xffffffff) 3848235233Sbschmidt continue; 3849235233Sbschmidt RAL_WRITE(sc, RT2860_TX_PWR_CFG(ridx), sc->txpow20mhz[ridx]); 3850235233Sbschmidt } 3851235233Sbschmidt 3852235233Sbschmidt for (ntries = 0; ntries < 100; ntries++) { 3853235233Sbschmidt tmp = RAL_READ(sc, RT2860_WPDMA_GLO_CFG); 3854235233Sbschmidt if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0) 3855235233Sbschmidt break; 3856235233Sbschmidt DELAY(1000); 3857235233Sbschmidt } 3858235233Sbschmidt if (ntries == 100) { 3859235233Sbschmidt device_printf(sc->sc_dev, "timeout waiting for DMA engine\n"); 3860235233Sbschmidt rt2860_stop_locked(sc); 3861235233Sbschmidt return; 3862235233Sbschmidt } 3863301575Skevlo tmp &= ~(RT2860_RX_DMA_BUSY | RT2860_RX_DMA_EN | RT2860_TX_DMA_BUSY | 3864301575Skevlo RT2860_TX_DMA_EN); 3865301575Skevlo tmp |= RT2860_TX_WB_DDONE; 3866235233Sbschmidt RAL_WRITE(sc, RT2860_WPDMA_GLO_CFG, tmp); 3867235233Sbschmidt 3868235233Sbschmidt /* reset Rx ring and all 6 Tx rings */ 3869235233Sbschmidt RAL_WRITE(sc, RT2860_WPDMA_RST_IDX, 0x1003f); 3870235233Sbschmidt 3871235233Sbschmidt /* PBF hardware reset */ 3872235233Sbschmidt RAL_WRITE(sc, RT2860_SYS_CTRL, 0xe1f); 3873235233Sbschmidt RAL_BARRIER_WRITE(sc); 3874235233Sbschmidt RAL_WRITE(sc, RT2860_SYS_CTRL, 0xe00); 3875235233Sbschmidt 3876235233Sbschmidt RAL_WRITE(sc, RT2860_PWR_PIN_CFG, RT2860_IO_RA_PE | RT2860_IO_RF_PE); 3877235233Sbschmidt 3878235233Sbschmidt RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, RT2860_BBP_HRST | RT2860_MAC_SRST); 3879235233Sbschmidt RAL_BARRIER_WRITE(sc); 3880235233Sbschmidt RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, 0); 3881235233Sbschmidt 3882278551Skevlo for (i = 0; i < nitems(rt2860_def_mac); i++) 3883235233Sbschmidt RAL_WRITE(sc, rt2860_def_mac[i].reg, rt2860_def_mac[i].val); 3884278551Skevlo if (sc->mac_ver >= 0x5390) 3885278551Skevlo RAL_WRITE(sc, RT2860_TX_SW_CFG0, 0x00000404); 3886278551Skevlo else if (sc->mac_ver >= 0x3071) { 3887235233Sbschmidt /* set delay of PA_PE assertion to 1us (unit of 0.25us) */ 3888235233Sbschmidt RAL_WRITE(sc, RT2860_TX_SW_CFG0, 3889235233Sbschmidt 4 << RT2860_DLY_PAPE_EN_SHIFT); 3890235233Sbschmidt } 3891235233Sbschmidt 3892235233Sbschmidt if (!(RAL_READ(sc, RT2860_PCI_CFG) & RT2860_PCI_CFG_PCI)) { 3893235233Sbschmidt sc->sc_flags |= RT2860_PCIE; 3894235233Sbschmidt /* PCIe has different clock cycle count than PCI */ 3895235233Sbschmidt tmp = RAL_READ(sc, RT2860_US_CYC_CNT); 3896235233Sbschmidt tmp = (tmp & ~0xff) | 0x7d; 3897235233Sbschmidt RAL_WRITE(sc, RT2860_US_CYC_CNT, tmp); 3898235233Sbschmidt } 3899235233Sbschmidt 3900235233Sbschmidt /* wait while MAC is busy */ 3901235233Sbschmidt for (ntries = 0; ntries < 100; ntries++) { 3902235233Sbschmidt if (!(RAL_READ(sc, RT2860_MAC_STATUS_REG) & 3903235233Sbschmidt (RT2860_RX_STATUS_BUSY | RT2860_TX_STATUS_BUSY))) 3904235233Sbschmidt break; 3905235233Sbschmidt DELAY(1000); 3906235233Sbschmidt } 3907235233Sbschmidt if (ntries == 100) { 3908235233Sbschmidt device_printf(sc->sc_dev, "timeout waiting for MAC\n"); 3909235233Sbschmidt rt2860_stop_locked(sc); 3910235233Sbschmidt return; 3911235233Sbschmidt } 3912235233Sbschmidt 3913235233Sbschmidt /* clear Host to MCU mailbox */ 3914235233Sbschmidt RAL_WRITE(sc, RT2860_H2M_BBPAGENT, 0); 3915235233Sbschmidt RAL_WRITE(sc, RT2860_H2M_MAILBOX, 0); 3916235233Sbschmidt 3917235233Sbschmidt rt2860_mcu_cmd(sc, RT2860_MCU_CMD_RFRESET, 0, 0); 3918235233Sbschmidt DELAY(1000); 3919235233Sbschmidt 3920235233Sbschmidt if ((error = rt2860_bbp_init(sc)) != 0) { 3921235233Sbschmidt rt2860_stop_locked(sc); 3922235233Sbschmidt return; 3923235233Sbschmidt } 3924235233Sbschmidt 3925235233Sbschmidt /* clear RX WCID search table */ 3926235233Sbschmidt RAL_SET_REGION_4(sc, RT2860_WCID_ENTRY(0), 0, 512); 3927235233Sbschmidt /* clear pairwise key table */ 3928235233Sbschmidt RAL_SET_REGION_4(sc, RT2860_PKEY(0), 0, 2048); 3929235233Sbschmidt /* clear IV/EIV table */ 3930235233Sbschmidt RAL_SET_REGION_4(sc, RT2860_IVEIV(0), 0, 512); 3931235233Sbschmidt /* clear WCID attribute table */ 3932235233Sbschmidt RAL_SET_REGION_4(sc, RT2860_WCID_ATTR(0), 0, 256); 3933235233Sbschmidt /* clear shared key table */ 3934235233Sbschmidt RAL_SET_REGION_4(sc, RT2860_SKEY(0, 0), 0, 8 * 32); 3935235233Sbschmidt /* clear shared key mode */ 3936235233Sbschmidt RAL_SET_REGION_4(sc, RT2860_SKEY_MODE_0_7, 0, 4); 3937235233Sbschmidt 3938235233Sbschmidt /* init Tx rings (4 EDCAs + HCCA + Mgt) */ 3939235233Sbschmidt for (qid = 0; qid < 6; qid++) { 3940235233Sbschmidt RAL_WRITE(sc, RT2860_TX_BASE_PTR(qid), sc->txq[qid].paddr); 3941235233Sbschmidt RAL_WRITE(sc, RT2860_TX_MAX_CNT(qid), RT2860_TX_RING_COUNT); 3942235233Sbschmidt RAL_WRITE(sc, RT2860_TX_CTX_IDX(qid), 0); 3943235233Sbschmidt } 3944235233Sbschmidt 3945235233Sbschmidt /* init Rx ring */ 3946235233Sbschmidt RAL_WRITE(sc, RT2860_RX_BASE_PTR, sc->rxq.paddr); 3947235233Sbschmidt RAL_WRITE(sc, RT2860_RX_MAX_CNT, RT2860_RX_RING_COUNT); 3948235233Sbschmidt RAL_WRITE(sc, RT2860_RX_CALC_IDX, RT2860_RX_RING_COUNT - 1); 3949235233Sbschmidt 3950235233Sbschmidt /* setup maximum buffer sizes */ 3951235233Sbschmidt RAL_WRITE(sc, RT2860_MAX_LEN_CFG, 1 << 12 | 3952235233Sbschmidt (MCLBYTES - sizeof (struct rt2860_rxwi) - 2)); 3953235233Sbschmidt 3954235233Sbschmidt for (ntries = 0; ntries < 100; ntries++) { 3955235233Sbschmidt tmp = RAL_READ(sc, RT2860_WPDMA_GLO_CFG); 3956235233Sbschmidt if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0) 3957235233Sbschmidt break; 3958235233Sbschmidt DELAY(1000); 3959235233Sbschmidt } 3960235233Sbschmidt if (ntries == 100) { 3961235233Sbschmidt device_printf(sc->sc_dev, "timeout waiting for DMA engine\n"); 3962235233Sbschmidt rt2860_stop_locked(sc); 3963235233Sbschmidt return; 3964235233Sbschmidt } 3965301575Skevlo tmp &= ~(RT2860_RX_DMA_BUSY | RT2860_RX_DMA_EN | RT2860_TX_DMA_BUSY | 3966301575Skevlo RT2860_TX_DMA_EN); 3967301575Skevlo tmp |= RT2860_TX_WB_DDONE; 3968235233Sbschmidt RAL_WRITE(sc, RT2860_WPDMA_GLO_CFG, tmp); 3969235233Sbschmidt 3970235233Sbschmidt /* disable interrupts mitigation */ 3971235233Sbschmidt RAL_WRITE(sc, RT2860_DELAY_INT_CFG, 0); 3972235233Sbschmidt 3973235233Sbschmidt /* write vendor-specific BBP values (from EEPROM) */ 3974235233Sbschmidt for (i = 0; i < 8; i++) { 3975235233Sbschmidt if (sc->bbp[i].reg == 0 || sc->bbp[i].reg == 0xff) 3976235233Sbschmidt continue; 3977235233Sbschmidt rt2860_mcu_bbp_write(sc, sc->bbp[i].reg, sc->bbp[i].val); 3978235233Sbschmidt } 3979235233Sbschmidt 3980235233Sbschmidt /* select Main antenna for 1T1R devices */ 3981235233Sbschmidt if (sc->rf_rev == RT3070_RF_2020 || 3982235233Sbschmidt sc->rf_rev == RT3070_RF_3020 || 3983278551Skevlo sc->rf_rev == RT3070_RF_3320 || 3984278551Skevlo sc->mac_ver == 0x5390) 3985235233Sbschmidt rt3090_set_rx_antenna(sc, 0); 3986235233Sbschmidt 3987235233Sbschmidt /* send LEDs operating mode to microcontroller */ 3988235233Sbschmidt rt2860_mcu_cmd(sc, RT2860_MCU_CMD_LED1, sc->led[0], 0); 3989235233Sbschmidt rt2860_mcu_cmd(sc, RT2860_MCU_CMD_LED2, sc->led[1], 0); 3990235233Sbschmidt rt2860_mcu_cmd(sc, RT2860_MCU_CMD_LED3, sc->led[2], 0); 3991235233Sbschmidt 3992278551Skevlo if (sc->mac_ver >= 0x5390) 3993278551Skevlo rt5390_rf_init(sc); 3994278551Skevlo else if (sc->mac_ver >= 0x3071) { 3995278551Skevlo if ((error = rt3090_rf_init(sc)) != 0) { 3996278551Skevlo rt2860_stop_locked(sc); 3997278551Skevlo return; 3998278551Skevlo } 3999278551Skevlo } 4000235233Sbschmidt 4001235233Sbschmidt rt2860_mcu_cmd(sc, RT2860_MCU_CMD_SLEEP, 0x02ff, 1); 4002235233Sbschmidt rt2860_mcu_cmd(sc, RT2860_MCU_CMD_WAKEUP, 0, 1); 4003235233Sbschmidt 4004278551Skevlo if (sc->mac_ver >= 0x5390) 4005278551Skevlo rt5390_rf_wakeup(sc); 4006278551Skevlo else if (sc->mac_ver >= 0x3071) 4007235233Sbschmidt rt3090_rf_wakeup(sc); 4008235233Sbschmidt 4009235233Sbschmidt /* disable non-existing Rx chains */ 4010235233Sbschmidt bbp3 = rt2860_mcu_bbp_read(sc, 3); 4011235233Sbschmidt bbp3 &= ~(1 << 3 | 1 << 4); 4012235233Sbschmidt if (sc->nrxchains == 2) 4013235233Sbschmidt bbp3 |= 1 << 3; 4014235233Sbschmidt else if (sc->nrxchains == 3) 4015235233Sbschmidt bbp3 |= 1 << 4; 4016235233Sbschmidt rt2860_mcu_bbp_write(sc, 3, bbp3); 4017235233Sbschmidt 4018235233Sbschmidt /* disable non-existing Tx chains */ 4019235233Sbschmidt bbp1 = rt2860_mcu_bbp_read(sc, 1); 4020235233Sbschmidt if (sc->ntxchains == 1) 4021235233Sbschmidt bbp1 = (bbp1 & ~(1 << 3 | 1 << 4)); 4022235233Sbschmidt else if (sc->mac_ver == 0x3593 && sc->ntxchains == 2) 4023235233Sbschmidt bbp1 = (bbp1 & ~(1 << 4)) | 1 << 3; 4024235233Sbschmidt else if (sc->mac_ver == 0x3593 && sc->ntxchains == 3) 4025235233Sbschmidt bbp1 = (bbp1 & ~(1 << 3)) | 1 << 4; 4026235233Sbschmidt rt2860_mcu_bbp_write(sc, 1, bbp1); 4027235233Sbschmidt 4028235233Sbschmidt if (sc->mac_ver >= 0x3071) 4029235233Sbschmidt rt3090_rf_setup(sc); 4030235233Sbschmidt 4031235233Sbschmidt /* select default channel */ 4032235233Sbschmidt rt2860_switch_chan(sc, ic->ic_curchan); 4033235233Sbschmidt 4034235233Sbschmidt /* reset RF from MCU */ 4035235233Sbschmidt rt2860_mcu_cmd(sc, RT2860_MCU_CMD_RFRESET, 0, 0); 4036235233Sbschmidt 4037235233Sbschmidt /* set RTS threshold */ 4038235233Sbschmidt tmp = RAL_READ(sc, RT2860_TX_RTS_CFG); 4039235233Sbschmidt tmp &= ~0xffff00; 4040235233Sbschmidt tmp |= IEEE80211_RTS_DEFAULT << 8; 4041235233Sbschmidt RAL_WRITE(sc, RT2860_TX_RTS_CFG, tmp); 4042235233Sbschmidt 4043235233Sbschmidt /* setup initial protection mode */ 4044287197Sglebius rt2860_updateprot(sc); 4045235233Sbschmidt 4046235233Sbschmidt /* turn radio LED on */ 4047235233Sbschmidt rt2860_set_leds(sc, RT2860_LED_RADIO); 4048235233Sbschmidt 4049235233Sbschmidt /* enable Tx/Rx DMA engine */ 4050235233Sbschmidt if ((error = rt2860_txrx_enable(sc)) != 0) { 4051235233Sbschmidt rt2860_stop_locked(sc); 4052235233Sbschmidt return; 4053235233Sbschmidt } 4054235233Sbschmidt 4055235233Sbschmidt /* clear pending interrupts */ 4056235233Sbschmidt RAL_WRITE(sc, RT2860_INT_STATUS, 0xffffffff); 4057235233Sbschmidt /* enable interrupts */ 4058235233Sbschmidt RAL_WRITE(sc, RT2860_INT_MASK, 0x3fffc); 4059235233Sbschmidt 4060235233Sbschmidt if (sc->sc_flags & RT2860_ADVANCED_PS) 4061235233Sbschmidt rt2860_mcu_cmd(sc, RT2860_MCU_CMD_PSLEVEL, sc->pslevel, 0); 4062235233Sbschmidt 4063290133Skevlo sc->sc_flags |= RT2860_RUNNING; 4064235233Sbschmidt 4065235233Sbschmidt callout_reset(&sc->watchdog_ch, hz, rt2860_watchdog, sc); 4066235233Sbschmidt} 4067235233Sbschmidt 4068235233Sbschmidtstatic void 4069235233Sbschmidtrt2860_stop(void *arg) 4070235233Sbschmidt{ 4071235233Sbschmidt struct rt2860_softc *sc = arg; 4072235233Sbschmidt 4073235233Sbschmidt RAL_LOCK(sc); 4074235233Sbschmidt rt2860_stop_locked(sc); 4075235233Sbschmidt RAL_UNLOCK(sc); 4076235233Sbschmidt} 4077235233Sbschmidt 4078235233Sbschmidtstatic void 4079235233Sbschmidtrt2860_stop_locked(struct rt2860_softc *sc) 4080235233Sbschmidt{ 4081235233Sbschmidt uint32_t tmp; 4082235233Sbschmidt int qid; 4083235233Sbschmidt 4084290133Skevlo if (sc->sc_flags & RT2860_RUNNING) 4085235233Sbschmidt rt2860_set_leds(sc, 0); /* turn all LEDs off */ 4086235233Sbschmidt 4087235233Sbschmidt callout_stop(&sc->watchdog_ch); 4088235233Sbschmidt sc->sc_tx_timer = 0; 4089290133Skevlo sc->sc_flags &= ~RT2860_RUNNING; 4090235233Sbschmidt 4091235233Sbschmidt /* disable interrupts */ 4092235233Sbschmidt RAL_WRITE(sc, RT2860_INT_MASK, 0); 4093235233Sbschmidt 4094235233Sbschmidt /* disable GP timer */ 4095235233Sbschmidt rt2860_set_gp_timer(sc, 0); 4096235233Sbschmidt 4097235233Sbschmidt /* disable Rx */ 4098235233Sbschmidt tmp = RAL_READ(sc, RT2860_MAC_SYS_CTRL); 4099235233Sbschmidt tmp &= ~(RT2860_MAC_RX_EN | RT2860_MAC_TX_EN); 4100235233Sbschmidt RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, tmp); 4101235233Sbschmidt 4102235233Sbschmidt /* reset adapter */ 4103235233Sbschmidt RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, RT2860_BBP_HRST | RT2860_MAC_SRST); 4104235233Sbschmidt RAL_BARRIER_WRITE(sc); 4105235233Sbschmidt RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, 0); 4106235233Sbschmidt 4107235233Sbschmidt /* reset Tx and Rx rings (and reclaim TXWIs) */ 4108235233Sbschmidt sc->qfullmsk = 0; 4109235233Sbschmidt for (qid = 0; qid < 6; qid++) 4110235233Sbschmidt rt2860_reset_tx_ring(sc, &sc->txq[qid]); 4111235233Sbschmidt rt2860_reset_rx_ring(sc, &sc->rxq); 4112235233Sbschmidt} 4113235233Sbschmidt 4114235233Sbschmidtint 4115235233Sbschmidtrt2860_load_microcode(struct rt2860_softc *sc) 4116235233Sbschmidt{ 4117235233Sbschmidt const struct firmware *fp; 4118235233Sbschmidt int ntries, error; 4119235233Sbschmidt 4120235233Sbschmidt RAL_LOCK_ASSERT(sc); 4121235233Sbschmidt 4122235233Sbschmidt RAL_UNLOCK(sc); 4123235233Sbschmidt fp = firmware_get("rt2860fw"); 4124235233Sbschmidt RAL_LOCK(sc); 4125235233Sbschmidt if (fp == NULL) { 4126235233Sbschmidt device_printf(sc->sc_dev, 4127235233Sbschmidt "unable to receive rt2860fw firmware image\n"); 4128235233Sbschmidt return EINVAL; 4129235233Sbschmidt } 4130235233Sbschmidt 4131235233Sbschmidt /* set "host program ram write selection" bit */ 4132235233Sbschmidt RAL_WRITE(sc, RT2860_SYS_CTRL, RT2860_HST_PM_SEL); 4133235233Sbschmidt /* write microcode image */ 4134235233Sbschmidt RAL_WRITE_REGION_1(sc, RT2860_FW_BASE, fp->data, fp->datasize); 4135235233Sbschmidt /* kick microcontroller unit */ 4136235233Sbschmidt RAL_WRITE(sc, RT2860_SYS_CTRL, 0); 4137235233Sbschmidt RAL_BARRIER_WRITE(sc); 4138235233Sbschmidt RAL_WRITE(sc, RT2860_SYS_CTRL, RT2860_MCU_RESET); 4139235233Sbschmidt 4140235233Sbschmidt RAL_WRITE(sc, RT2860_H2M_BBPAGENT, 0); 4141235233Sbschmidt RAL_WRITE(sc, RT2860_H2M_MAILBOX, 0); 4142235233Sbschmidt 4143235233Sbschmidt /* wait until microcontroller is ready */ 4144235233Sbschmidt RAL_BARRIER_READ_WRITE(sc); 4145235233Sbschmidt for (ntries = 0; ntries < 1000; ntries++) { 4146235233Sbschmidt if (RAL_READ(sc, RT2860_SYS_CTRL) & RT2860_MCU_READY) 4147235233Sbschmidt break; 4148235233Sbschmidt DELAY(1000); 4149235233Sbschmidt } 4150235233Sbschmidt if (ntries == 1000) { 4151235233Sbschmidt device_printf(sc->sc_dev, 4152235233Sbschmidt "timeout waiting for MCU to initialize\n"); 4153235233Sbschmidt error = ETIMEDOUT; 4154235233Sbschmidt } else 4155235233Sbschmidt error = 0; 4156235233Sbschmidt 4157235233Sbschmidt firmware_put(fp, FIRMWARE_UNLOAD); 4158235233Sbschmidt return error; 4159235233Sbschmidt} 4160235233Sbschmidt 4161235233Sbschmidt/* 4162235233Sbschmidt * This function is called periodically to adjust Tx power based on 4163235233Sbschmidt * temperature variation. 4164235233Sbschmidt */ 4165235233Sbschmidt#ifdef NOT_YET 4166235233Sbschmidtstatic void 4167235233Sbschmidtrt2860_calib(struct rt2860_softc *sc) 4168235233Sbschmidt{ 4169235233Sbschmidt struct ieee80211com *ic = &sc->sc_ic; 4170235233Sbschmidt const uint8_t *tssi; 4171235233Sbschmidt uint8_t step, bbp49; 4172235233Sbschmidt int8_t ridx, d; 4173235233Sbschmidt 4174235233Sbschmidt /* read current temperature */ 4175235233Sbschmidt bbp49 = rt2860_mcu_bbp_read(sc, 49); 4176235233Sbschmidt 4177235233Sbschmidt if (IEEE80211_IS_CHAN_2GHZ(ic->ic_bss->ni_chan)) { 4178235233Sbschmidt tssi = &sc->tssi_2ghz[4]; 4179235233Sbschmidt step = sc->step_2ghz; 4180235233Sbschmidt } else { 4181235233Sbschmidt tssi = &sc->tssi_5ghz[4]; 4182235233Sbschmidt step = sc->step_5ghz; 4183235233Sbschmidt } 4184235233Sbschmidt 4185235233Sbschmidt if (bbp49 < tssi[0]) { /* lower than reference */ 4186235233Sbschmidt /* use higher Tx power than default */ 4187235233Sbschmidt for (d = 0; d > -4 && bbp49 <= tssi[d - 1]; d--); 4188235233Sbschmidt } else if (bbp49 > tssi[0]) { /* greater than reference */ 4189235233Sbschmidt /* use lower Tx power than default */ 4190235233Sbschmidt for (d = 0; d < +4 && bbp49 >= tssi[d + 1]; d++); 4191235233Sbschmidt } else { 4192235233Sbschmidt /* use default Tx power */ 4193235233Sbschmidt d = 0; 4194235233Sbschmidt } 4195235233Sbschmidt d *= step; 4196235233Sbschmidt 4197235233Sbschmidt DPRINTF(("BBP49=0x%02x, adjusting Tx power by %d\n", bbp49, d)); 4198235233Sbschmidt 4199235233Sbschmidt /* write adjusted Tx power values for each Tx rate */ 4200235233Sbschmidt for (ridx = 0; ridx < 5; ridx++) { 4201235233Sbschmidt if (sc->txpow20mhz[ridx] == 0xffffffff) 4202235233Sbschmidt continue; 4203235233Sbschmidt RAL_WRITE(sc, RT2860_TX_PWR_CFG(ridx), 4204235233Sbschmidt b4inc(sc->txpow20mhz[ridx], d)); 4205235233Sbschmidt } 4206235233Sbschmidt} 4207235233Sbschmidt#endif 4208235233Sbschmidt 4209235233Sbschmidtstatic void 4210235233Sbschmidtrt3090_set_rx_antenna(struct rt2860_softc *sc, int aux) 4211235233Sbschmidt{ 4212235233Sbschmidt uint32_t tmp; 4213235233Sbschmidt 4214235233Sbschmidt if (aux) { 4215278551Skevlo if (sc->mac_ver == 0x5390) { 4216278551Skevlo rt2860_mcu_bbp_write(sc, 152, 4217278551Skevlo rt2860_mcu_bbp_read(sc, 152) & ~0x80); 4218278551Skevlo } else { 4219278551Skevlo tmp = RAL_READ(sc, RT2860_PCI_EECTRL); 4220278551Skevlo RAL_WRITE(sc, RT2860_PCI_EECTRL, tmp & ~RT2860_C); 4221278551Skevlo tmp = RAL_READ(sc, RT2860_GPIO_CTRL); 4222278551Skevlo RAL_WRITE(sc, RT2860_GPIO_CTRL, (tmp & ~0x0808) | 0x08); 4223278551Skevlo } 4224235233Sbschmidt } else { 4225278551Skevlo if (sc->mac_ver == 0x5390) { 4226278551Skevlo rt2860_mcu_bbp_write(sc, 152, 4227278551Skevlo rt2860_mcu_bbp_read(sc, 152) | 0x80); 4228278551Skevlo } else { 4229278551Skevlo tmp = RAL_READ(sc, RT2860_PCI_EECTRL); 4230278551Skevlo RAL_WRITE(sc, RT2860_PCI_EECTRL, tmp | RT2860_C); 4231278551Skevlo tmp = RAL_READ(sc, RT2860_GPIO_CTRL); 4232278551Skevlo RAL_WRITE(sc, RT2860_GPIO_CTRL, tmp & ~0x0808); 4233278551Skevlo } 4234235233Sbschmidt } 4235235233Sbschmidt} 4236235233Sbschmidt 4237235233Sbschmidtstatic void 4238235233Sbschmidtrt2860_switch_chan(struct rt2860_softc *sc, struct ieee80211_channel *c) 4239235233Sbschmidt{ 4240287197Sglebius struct ieee80211com *ic = &sc->sc_ic; 4241235233Sbschmidt u_int chan, group; 4242235233Sbschmidt 4243235233Sbschmidt chan = ieee80211_chan2ieee(ic, c); 4244235233Sbschmidt if (chan == 0 || chan == IEEE80211_CHAN_ANY) 4245235233Sbschmidt return; 4246235233Sbschmidt 4247278551Skevlo if (sc->mac_ver >= 0x5390) 4248278551Skevlo rt5390_set_chan(sc, chan); 4249278551Skevlo else if (sc->mac_ver >= 0x3071) 4250235233Sbschmidt rt3090_set_chan(sc, chan); 4251235233Sbschmidt else 4252235233Sbschmidt rt2860_set_chan(sc, chan); 4253235233Sbschmidt 4254235233Sbschmidt /* determine channel group */ 4255235233Sbschmidt if (chan <= 14) 4256235233Sbschmidt group = 0; 4257235233Sbschmidt else if (chan <= 64) 4258235233Sbschmidt group = 1; 4259235233Sbschmidt else if (chan <= 128) 4260235233Sbschmidt group = 2; 4261235233Sbschmidt else 4262235233Sbschmidt group = 3; 4263235233Sbschmidt 4264235233Sbschmidt /* XXX necessary only when group has changed! */ 4265278551Skevlo if (sc->mac_ver < 0x5390) 4266278551Skevlo rt2860_select_chan_group(sc, group); 4267235233Sbschmidt 4268235233Sbschmidt DELAY(1000); 4269235233Sbschmidt} 4270235233Sbschmidt 4271235233Sbschmidtstatic int 4272235233Sbschmidtrt2860_setup_beacon(struct rt2860_softc *sc, struct ieee80211vap *vap) 4273235233Sbschmidt{ 4274235233Sbschmidt struct ieee80211com *ic = vap->iv_ic; 4275235233Sbschmidt struct rt2860_txwi txwi; 4276235233Sbschmidt struct mbuf *m; 4277235233Sbschmidt int ridx; 4278235233Sbschmidt 4279288636Sadrian if ((m = ieee80211_beacon_alloc(vap->iv_bss)) == NULL) 4280235233Sbschmidt return ENOBUFS; 4281235233Sbschmidt 4282235233Sbschmidt memset(&txwi, 0, sizeof txwi); 4283235233Sbschmidt txwi.wcid = 0xff; 4284235233Sbschmidt txwi.len = htole16(m->m_pkthdr.len); 4285235233Sbschmidt /* send beacons at the lowest available rate */ 4286235233Sbschmidt ridx = IEEE80211_IS_CHAN_5GHZ(ic->ic_bsschan) ? 4287235233Sbschmidt RT2860_RIDX_OFDM6 : RT2860_RIDX_CCK1; 4288235233Sbschmidt txwi.phy = htole16(rt2860_rates[ridx].mcs); 4289235233Sbschmidt if (rt2860_rates[ridx].phy == IEEE80211_T_OFDM) 4290235233Sbschmidt txwi.phy |= htole16(RT2860_PHY_OFDM); 4291235233Sbschmidt txwi.txop = RT2860_TX_TXOP_HT; 4292235233Sbschmidt txwi.flags = RT2860_TX_TS; 4293235233Sbschmidt txwi.xflags = RT2860_TX_NSEQ; 4294235233Sbschmidt 4295235233Sbschmidt RAL_WRITE_REGION_1(sc, RT2860_BCN_BASE(0), 4296235233Sbschmidt (uint8_t *)&txwi, sizeof txwi); 4297235233Sbschmidt RAL_WRITE_REGION_1(sc, RT2860_BCN_BASE(0) + sizeof txwi, 4298235233Sbschmidt mtod(m, uint8_t *), m->m_pkthdr.len); 4299235233Sbschmidt 4300235233Sbschmidt m_freem(m); 4301235233Sbschmidt 4302235233Sbschmidt return 0; 4303235233Sbschmidt} 4304235233Sbschmidt 4305235233Sbschmidtstatic void 4306235233Sbschmidtrt2860_enable_tsf_sync(struct rt2860_softc *sc) 4307235233Sbschmidt{ 4308287197Sglebius struct ieee80211com *ic = &sc->sc_ic; 4309235233Sbschmidt struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); 4310235233Sbschmidt uint32_t tmp; 4311235233Sbschmidt 4312235233Sbschmidt tmp = RAL_READ(sc, RT2860_BCN_TIME_CFG); 4313235233Sbschmidt 4314235233Sbschmidt tmp &= ~0x1fffff; 4315235233Sbschmidt tmp |= vap->iv_bss->ni_intval * 16; 4316235233Sbschmidt tmp |= RT2860_TSF_TIMER_EN | RT2860_TBTT_TIMER_EN; 4317235233Sbschmidt if (vap->iv_opmode == IEEE80211_M_STA) { 4318235233Sbschmidt /* 4319235233Sbschmidt * Local TSF is always updated with remote TSF on beacon 4320235233Sbschmidt * reception. 4321235233Sbschmidt */ 4322235233Sbschmidt tmp |= 1 << RT2860_TSF_SYNC_MODE_SHIFT; 4323235233Sbschmidt } 4324235233Sbschmidt else if (vap->iv_opmode == IEEE80211_M_IBSS || 4325235233Sbschmidt vap->iv_opmode == IEEE80211_M_MBSS) { 4326235233Sbschmidt tmp |= RT2860_BCN_TX_EN; 4327235233Sbschmidt /* 4328235233Sbschmidt * Local TSF is updated with remote TSF on beacon reception 4329235233Sbschmidt * only if the remote TSF is greater than local TSF. 4330235233Sbschmidt */ 4331235233Sbschmidt tmp |= 2 << RT2860_TSF_SYNC_MODE_SHIFT; 4332235233Sbschmidt } else if (vap->iv_opmode == IEEE80211_M_HOSTAP) { 4333235233Sbschmidt tmp |= RT2860_BCN_TX_EN; 4334235233Sbschmidt /* SYNC with nobody */ 4335235233Sbschmidt tmp |= 3 << RT2860_TSF_SYNC_MODE_SHIFT; 4336235233Sbschmidt } 4337235233Sbschmidt 4338235233Sbschmidt RAL_WRITE(sc, RT2860_BCN_TIME_CFG, tmp); 4339235233Sbschmidt} 4340