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