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