Index: head/sys/dev/ral/rt2860.c =================================================================== --- head/sys/dev/ral/rt2860.c (revision 300005) +++ head/sys/dev/ral/rt2860.c (revision 300006) @@ -1,4330 +1,4308 @@ /*- * Copyright (c) 2007-2010 Damien Bergamini * Copyright (c) 2012 Bernhard Schmidt * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $OpenBSD: rt2860.c,v 1.65 2010/10/23 14:24:54 damien Exp $ */ #include __FBSDID("$FreeBSD$"); /*- * Ralink Technology RT2860/RT3090/RT3390/RT3562/RT5390/RT5392 chipset driver * http://www.ralinktech.com/ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define RAL_DEBUG #ifdef RAL_DEBUG #define DPRINTF(x) do { if (sc->sc_debug > 0) printf x; } while (0) #define DPRINTFN(n, x) do { if (sc->sc_debug >= (n)) printf x; } while (0) #else #define DPRINTF(x) #define DPRINTFN(n, x) #endif static struct ieee80211vap *rt2860_vap_create(struct ieee80211com *, const char [IFNAMSIZ], int, enum ieee80211_opmode, int, const uint8_t [IEEE80211_ADDR_LEN], const uint8_t [IEEE80211_ADDR_LEN]); static void rt2860_vap_delete(struct ieee80211vap *); static void rt2860_dma_map_addr(void *, bus_dma_segment_t *, int, int); static int rt2860_alloc_tx_ring(struct rt2860_softc *, struct rt2860_tx_ring *); static void rt2860_reset_tx_ring(struct rt2860_softc *, struct rt2860_tx_ring *); static void rt2860_free_tx_ring(struct rt2860_softc *, struct rt2860_tx_ring *); static int rt2860_alloc_tx_pool(struct rt2860_softc *); static void rt2860_free_tx_pool(struct rt2860_softc *); static int rt2860_alloc_rx_ring(struct rt2860_softc *, struct rt2860_rx_ring *); static void rt2860_reset_rx_ring(struct rt2860_softc *, struct rt2860_rx_ring *); static void rt2860_free_rx_ring(struct rt2860_softc *, struct rt2860_rx_ring *); static void rt2860_updatestats(struct rt2860_softc *); static void rt2860_newassoc(struct ieee80211_node *, int); static void rt2860_node_free(struct ieee80211_node *); #ifdef IEEE80211_HT static int rt2860_ampdu_rx_start(struct ieee80211com *, struct ieee80211_node *, uint8_t); static void rt2860_ampdu_rx_stop(struct ieee80211com *, struct ieee80211_node *, uint8_t); #endif static int rt2860_newstate(struct ieee80211vap *, enum ieee80211_state, int); static uint16_t rt3090_efuse_read_2(struct rt2860_softc *, uint16_t); static uint16_t rt2860_eeprom_read_2(struct rt2860_softc *, uint16_t); static void rt2860_intr_coherent(struct rt2860_softc *); static void rt2860_drain_stats_fifo(struct rt2860_softc *); static void rt2860_tx_intr(struct rt2860_softc *, int); static void rt2860_rx_intr(struct rt2860_softc *); static void rt2860_tbtt_intr(struct rt2860_softc *); static void rt2860_gp_intr(struct rt2860_softc *); static int rt2860_tx(struct rt2860_softc *, struct mbuf *, struct ieee80211_node *); static int rt2860_raw_xmit(struct ieee80211_node *, struct mbuf *, const struct ieee80211_bpf_params *); static int rt2860_tx_raw(struct rt2860_softc *, struct mbuf *, struct ieee80211_node *, const struct ieee80211_bpf_params *params); static int rt2860_transmit(struct ieee80211com *, struct mbuf *); static void rt2860_start(struct rt2860_softc *); static void rt2860_watchdog(void *); static void rt2860_parent(struct ieee80211com *); static void rt2860_mcu_bbp_write(struct rt2860_softc *, uint8_t, uint8_t); static uint8_t rt2860_mcu_bbp_read(struct rt2860_softc *, uint8_t); static void rt2860_rf_write(struct rt2860_softc *, uint8_t, uint32_t); static uint8_t rt3090_rf_read(struct rt2860_softc *, uint8_t); static void rt3090_rf_write(struct rt2860_softc *, uint8_t, uint8_t); static int rt2860_mcu_cmd(struct rt2860_softc *, uint8_t, uint16_t, int); static void rt2860_enable_mrr(struct rt2860_softc *); static void rt2860_set_txpreamble(struct rt2860_softc *); static void rt2860_set_basicrates(struct rt2860_softc *, const struct ieee80211_rateset *); static void rt2860_scan_start(struct ieee80211com *); static void rt2860_scan_end(struct ieee80211com *); static void rt2860_set_channel(struct ieee80211com *); static void rt2860_select_chan_group(struct rt2860_softc *, int); static void rt2860_set_chan(struct rt2860_softc *, u_int); static void rt3090_set_chan(struct rt2860_softc *, u_int); static void rt5390_set_chan(struct rt2860_softc *, u_int); static int rt3090_rf_init(struct rt2860_softc *); static void rt5390_rf_init(struct rt2860_softc *); static void rt3090_rf_wakeup(struct rt2860_softc *); static void rt5390_rf_wakeup(struct rt2860_softc *); static int rt3090_filter_calib(struct rt2860_softc *, uint8_t, uint8_t, uint8_t *); static void rt3090_rf_setup(struct rt2860_softc *); static void rt2860_set_leds(struct rt2860_softc *, uint16_t); static void rt2860_set_gp_timer(struct rt2860_softc *, int); static void rt2860_set_bssid(struct rt2860_softc *, const uint8_t *); static void rt2860_set_macaddr(struct rt2860_softc *, const uint8_t *); static void rt2860_update_promisc(struct ieee80211com *); static void rt2860_updateslot(struct ieee80211com *); static void rt2860_updateprot(struct rt2860_softc *); static int rt2860_updateedca(struct ieee80211com *); #ifdef HW_CRYPTO static int rt2860_set_key(struct ieee80211com *, struct ieee80211_node *, struct ieee80211_key *); static void rt2860_delete_key(struct ieee80211com *, struct ieee80211_node *, struct ieee80211_key *); #endif static int8_t rt2860_rssi2dbm(struct rt2860_softc *, uint8_t, uint8_t); -static const char *rt2860_get_rf(uint8_t); +static const char *rt2860_get_rf(uint16_t); static int rt2860_read_eeprom(struct rt2860_softc *, uint8_t macaddr[IEEE80211_ADDR_LEN]); static int rt2860_bbp_init(struct rt2860_softc *); static void rt5390_bbp_init(struct rt2860_softc *); static int rt2860_txrx_enable(struct rt2860_softc *); static void rt2860_init(void *); static void rt2860_init_locked(struct rt2860_softc *); static void rt2860_stop(void *); static void rt2860_stop_locked(struct rt2860_softc *); static int rt2860_load_microcode(struct rt2860_softc *); #ifdef NOT_YET static void rt2860_calib(struct rt2860_softc *); #endif static void rt3090_set_rx_antenna(struct rt2860_softc *, int); static void rt2860_switch_chan(struct rt2860_softc *, struct ieee80211_channel *); static int rt2860_setup_beacon(struct rt2860_softc *, struct ieee80211vap *); static void rt2860_enable_tsf_sync(struct rt2860_softc *); static const struct { uint32_t reg; uint32_t val; } rt2860_def_mac[] = { RT2860_DEF_MAC }; static const struct { uint8_t reg; uint8_t val; } rt2860_def_bbp[] = { RT2860_DEF_BBP }, rt5390_def_bbp[] = { RT5390_DEF_BBP }; static const struct rfprog { uint8_t chan; uint32_t r1, r2, r3, r4; } rt2860_rf2850[] = { RT2860_RF2850 }; struct { uint8_t n, r, k; } rt3090_freqs[] = { RT3070_RF3052 }; static const struct { uint8_t reg; uint8_t val; } rt3090_def_rf[] = { RT3070_DEF_RF }, rt5390_def_rf[] = { RT5390_DEF_RF }, rt5392_def_rf[] = { RT5392_DEF_RF }; int rt2860_attach(device_t dev, int id) { struct rt2860_softc *sc = device_get_softc(dev); struct ieee80211com *ic = &sc->sc_ic; uint32_t tmp; uint8_t bands[IEEE80211_MODE_BYTES]; int error, ntries, qid; sc->sc_dev = dev; sc->sc_debug = 0; mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, MTX_DEF | MTX_RECURSE); callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0); mbufq_init(&sc->sc_snd, ifqmaxlen); /* wait for NIC to initialize */ for (ntries = 0; ntries < 100; ntries++) { tmp = RAL_READ(sc, RT2860_ASIC_VER_ID); if (tmp != 0 && tmp != 0xffffffff) break; DELAY(10); } if (ntries == 100) { device_printf(sc->sc_dev, "timeout waiting for NIC to initialize\n"); error = EIO; goto fail1; } sc->mac_ver = tmp >> 16; sc->mac_rev = tmp & 0xffff; if (sc->mac_ver != 0x2860 && (id == 0x0681 || id == 0x0781 || id == 0x1059)) sc->sc_flags |= RT2860_ADVANCED_PS; /* retrieve RF rev. no and various other things from EEPROM */ rt2860_read_eeprom(sc, ic->ic_macaddr); device_printf(sc->sc_dev, "MAC/BBP RT%X (rev 0x%04X), " "RF %s (MIMO %dT%dR), address %6D\n", sc->mac_ver, sc->mac_rev, rt2860_get_rf(sc->rf_rev), sc->ntxchains, sc->nrxchains, ic->ic_macaddr, ":"); /* * Allocate Tx (4 EDCAs + HCCA + Mgt) and Rx rings. */ for (qid = 0; qid < 6; qid++) { if ((error = rt2860_alloc_tx_ring(sc, &sc->txq[qid])) != 0) { device_printf(sc->sc_dev, "could not allocate Tx ring %d\n", qid); goto fail2; } } if ((error = rt2860_alloc_rx_ring(sc, &sc->rxq)) != 0) { device_printf(sc->sc_dev, "could not allocate Rx ring\n"); goto fail2; } if ((error = rt2860_alloc_tx_pool(sc)) != 0) { device_printf(sc->sc_dev, "could not allocate Tx pool\n"); goto fail3; } /* mgmt ring is broken on RT2860C, use EDCA AC VO ring instead */ sc->mgtqid = (sc->mac_ver == 0x2860 && sc->mac_rev == 0x0100) ? WME_AC_VO : 5; ic->ic_softc = sc; ic->ic_name = device_get_nameunit(dev); ic->ic_opmode = IEEE80211_M_STA; ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ /* set device capabilities */ ic->ic_caps = IEEE80211_C_STA /* station mode */ | IEEE80211_C_IBSS /* ibss, nee adhoc, mode */ | IEEE80211_C_HOSTAP /* hostap mode */ | IEEE80211_C_MONITOR /* monitor mode */ | IEEE80211_C_AHDEMO /* adhoc demo mode */ | IEEE80211_C_WDS /* 4-address traffic works */ | IEEE80211_C_MBSS /* mesh point link mode */ | IEEE80211_C_SHPREAMBLE /* short preamble supported */ | IEEE80211_C_SHSLOT /* short slot time supported */ | IEEE80211_C_WPA /* capable of WPA1+WPA2 */ #if 0 | IEEE80211_C_BGSCAN /* capable of bg scanning */ #endif | IEEE80211_C_WME /* 802.11e */ ; memset(bands, 0, sizeof(bands)); setbit(bands, IEEE80211_MODE_11B); setbit(bands, IEEE80211_MODE_11G); if (sc->rf_rev == RT2860_RF_2750 || sc->rf_rev == RT2860_RF_2850) setbit(bands, IEEE80211_MODE_11A); ieee80211_init_channels(ic, NULL, bands); ieee80211_ifattach(ic); ic->ic_wme.wme_update = rt2860_updateedca; ic->ic_scan_start = rt2860_scan_start; ic->ic_scan_end = rt2860_scan_end; ic->ic_set_channel = rt2860_set_channel; ic->ic_updateslot = rt2860_updateslot; ic->ic_update_promisc = rt2860_update_promisc; ic->ic_raw_xmit = rt2860_raw_xmit; sc->sc_node_free = ic->ic_node_free; ic->ic_node_free = rt2860_node_free; ic->ic_newassoc = rt2860_newassoc; ic->ic_transmit = rt2860_transmit; ic->ic_parent = rt2860_parent; ic->ic_vap_create = rt2860_vap_create; ic->ic_vap_delete = rt2860_vap_delete; ieee80211_radiotap_attach(ic, &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), RT2860_TX_RADIOTAP_PRESENT, &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap), RT2860_RX_RADIOTAP_PRESENT); #ifdef RAL_DEBUG SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "debug", CTLFLAG_RW, &sc->sc_debug, 0, "debug msgs"); #endif if (bootverbose) ieee80211_announce(ic); return 0; fail3: rt2860_free_rx_ring(sc, &sc->rxq); fail2: while (--qid >= 0) rt2860_free_tx_ring(sc, &sc->txq[qid]); fail1: mtx_destroy(&sc->sc_mtx); return error; } int rt2860_detach(void *xsc) { struct rt2860_softc *sc = xsc; struct ieee80211com *ic = &sc->sc_ic; int qid; RAL_LOCK(sc); rt2860_stop_locked(sc); RAL_UNLOCK(sc); ieee80211_ifdetach(ic); mbufq_drain(&sc->sc_snd); for (qid = 0; qid < 6; qid++) rt2860_free_tx_ring(sc, &sc->txq[qid]); rt2860_free_rx_ring(sc, &sc->rxq); rt2860_free_tx_pool(sc); mtx_destroy(&sc->sc_mtx); return 0; } void rt2860_shutdown(void *xsc) { struct rt2860_softc *sc = xsc; rt2860_stop(sc); } void rt2860_suspend(void *xsc) { struct rt2860_softc *sc = xsc; rt2860_stop(sc); } void rt2860_resume(void *xsc) { struct rt2860_softc *sc = xsc; if (sc->sc_ic.ic_nrunning > 0) rt2860_init(sc); } static struct ieee80211vap * rt2860_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, enum ieee80211_opmode opmode, int flags, const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t mac[IEEE80211_ADDR_LEN]) { struct rt2860_softc *sc = ic->ic_softc; struct rt2860_vap *rvp; struct ieee80211vap *vap; switch (opmode) { case IEEE80211_M_STA: case IEEE80211_M_IBSS: case IEEE80211_M_AHDEMO: case IEEE80211_M_MONITOR: case IEEE80211_M_HOSTAP: case IEEE80211_M_MBSS: /* XXXRP: TBD */ if (!TAILQ_EMPTY(&ic->ic_vaps)) { device_printf(sc->sc_dev, "only 1 vap supported\n"); return NULL; } if (opmode == IEEE80211_M_STA) flags |= IEEE80211_CLONE_NOBEACONS; break; case IEEE80211_M_WDS: if (TAILQ_EMPTY(&ic->ic_vaps) || ic->ic_opmode != IEEE80211_M_HOSTAP) { device_printf(sc->sc_dev, "wds only supported in ap mode\n"); return NULL; } /* * Silently remove any request for a unique * bssid; WDS vap's always share the local * mac address. */ flags &= ~IEEE80211_CLONE_BSSID; break; default: device_printf(sc->sc_dev, "unknown opmode %d\n", opmode); return NULL; } rvp = malloc(sizeof(struct rt2860_vap), M_80211_VAP, M_WAITOK | M_ZERO); vap = &rvp->ral_vap; ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid); /* override state transition machine */ rvp->ral_newstate = vap->iv_newstate; vap->iv_newstate = rt2860_newstate; #if 0 vap->iv_update_beacon = rt2860_beacon_update; #endif /* HW supports up to 255 STAs (0-254) in HostAP and IBSS modes */ vap->iv_max_aid = min(IEEE80211_AID_MAX, RT2860_WCID_MAX); ieee80211_ratectl_init(vap); /* complete setup */ ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status, mac); if (TAILQ_FIRST(&ic->ic_vaps) == vap) ic->ic_opmode = opmode; return vap; } static void rt2860_vap_delete(struct ieee80211vap *vap) { struct rt2860_vap *rvp = RT2860_VAP(vap); ieee80211_ratectl_deinit(vap); ieee80211_vap_detach(vap); free(rvp, M_80211_VAP); } static void rt2860_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error) { if (error != 0) return; KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); *(bus_addr_t *)arg = segs[0].ds_addr; } static int rt2860_alloc_tx_ring(struct rt2860_softc *sc, struct rt2860_tx_ring *ring) { int size, error; size = RT2860_TX_RING_COUNT * sizeof (struct rt2860_txd); error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 16, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, size, 1, size, 0, NULL, NULL, &ring->desc_dmat); if (error != 0) { device_printf(sc->sc_dev, "could not create desc DMA tag\n"); goto fail; } error = bus_dmamem_alloc(ring->desc_dmat, (void **)&ring->txd, BUS_DMA_NOWAIT | BUS_DMA_ZERO, &ring->desc_map); if (error != 0) { device_printf(sc->sc_dev, "could not allocate DMA memory\n"); goto fail; } error = bus_dmamap_load(ring->desc_dmat, ring->desc_map, ring->txd, size, rt2860_dma_map_addr, &ring->paddr, 0); if (error != 0) { device_printf(sc->sc_dev, "could not load desc DMA map\n"); goto fail; } bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_PREWRITE); return 0; fail: rt2860_free_tx_ring(sc, ring); return error; } void rt2860_reset_tx_ring(struct rt2860_softc *sc, struct rt2860_tx_ring *ring) { struct rt2860_tx_data *data; int i; for (i = 0; i < RT2860_TX_RING_COUNT; i++) { if ((data = ring->data[i]) == NULL) continue; /* nothing mapped in this slot */ if (data->m != NULL) { bus_dmamap_sync(sc->txwi_dmat, data->map, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(sc->txwi_dmat, data->map); m_freem(data->m); data->m = NULL; } if (data->ni != NULL) { ieee80211_free_node(data->ni); data->ni = NULL; } SLIST_INSERT_HEAD(&sc->data_pool, data, next); ring->data[i] = NULL; } ring->queued = 0; ring->cur = ring->next = 0; } void rt2860_free_tx_ring(struct rt2860_softc *sc, struct rt2860_tx_ring *ring) { struct rt2860_tx_data *data; int i; if (ring->txd != NULL) { bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(ring->desc_dmat, ring->desc_map); bus_dmamem_free(ring->desc_dmat, ring->txd, ring->desc_map); } if (ring->desc_dmat != NULL) bus_dma_tag_destroy(ring->desc_dmat); for (i = 0; i < RT2860_TX_RING_COUNT; i++) { if ((data = ring->data[i]) == NULL) continue; /* nothing mapped in this slot */ if (data->m != NULL) { bus_dmamap_sync(sc->txwi_dmat, data->map, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(sc->txwi_dmat, data->map); m_freem(data->m); } if (data->ni != NULL) ieee80211_free_node(data->ni); SLIST_INSERT_HEAD(&sc->data_pool, data, next); } } /* * Allocate a pool of TX Wireless Information blocks. */ int rt2860_alloc_tx_pool(struct rt2860_softc *sc) { caddr_t vaddr; bus_addr_t paddr; int i, size, error; size = RT2860_TX_POOL_COUNT * RT2860_TXWI_DMASZ; /* init data_pool early in case of failure.. */ SLIST_INIT(&sc->data_pool); error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, size, 1, size, 0, NULL, NULL, &sc->txwi_dmat); if (error != 0) { device_printf(sc->sc_dev, "could not create txwi DMA tag\n"); goto fail; } error = bus_dmamem_alloc(sc->txwi_dmat, (void **)&sc->txwi_vaddr, BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sc->txwi_map); if (error != 0) { device_printf(sc->sc_dev, "could not allocate DMA memory\n"); goto fail; } error = bus_dmamap_load(sc->txwi_dmat, sc->txwi_map, sc->txwi_vaddr, size, rt2860_dma_map_addr, &paddr, 0); if (error != 0) { device_printf(sc->sc_dev, "could not load txwi DMA map\n"); goto fail; } bus_dmamap_sync(sc->txwi_dmat, sc->txwi_map, BUS_DMASYNC_PREWRITE); vaddr = sc->txwi_vaddr; for (i = 0; i < RT2860_TX_POOL_COUNT; i++) { struct rt2860_tx_data *data = &sc->data[i]; error = bus_dmamap_create(sc->txwi_dmat, 0, &data->map); if (error != 0) { device_printf(sc->sc_dev, "could not create DMA map\n"); goto fail; } data->txwi = (struct rt2860_txwi *)vaddr; data->paddr = paddr; vaddr += RT2860_TXWI_DMASZ; paddr += RT2860_TXWI_DMASZ; SLIST_INSERT_HEAD(&sc->data_pool, data, next); } return 0; fail: rt2860_free_tx_pool(sc); return error; } void rt2860_free_tx_pool(struct rt2860_softc *sc) { if (sc->txwi_vaddr != NULL) { bus_dmamap_sync(sc->txwi_dmat, sc->txwi_map, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(sc->txwi_dmat, sc->txwi_map); bus_dmamem_free(sc->txwi_dmat, sc->txwi_vaddr, sc->txwi_map); } if (sc->txwi_dmat != NULL) bus_dma_tag_destroy(sc->txwi_dmat); while (!SLIST_EMPTY(&sc->data_pool)) { struct rt2860_tx_data *data; data = SLIST_FIRST(&sc->data_pool); bus_dmamap_destroy(sc->txwi_dmat, data->map); SLIST_REMOVE_HEAD(&sc->data_pool, next); } } int rt2860_alloc_rx_ring(struct rt2860_softc *sc, struct rt2860_rx_ring *ring) { bus_addr_t physaddr; int i, size, error; size = RT2860_RX_RING_COUNT * sizeof (struct rt2860_rxd); error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 16, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, size, 1, size, 0, NULL, NULL, &ring->desc_dmat); if (error != 0) { device_printf(sc->sc_dev, "could not create desc DMA tag\n"); goto fail; } error = bus_dmamem_alloc(ring->desc_dmat, (void **)&ring->rxd, BUS_DMA_NOWAIT | BUS_DMA_ZERO, &ring->desc_map); if (error != 0) { device_printf(sc->sc_dev, "could not allocate DMA memory\n"); goto fail; } error = bus_dmamap_load(ring->desc_dmat, ring->desc_map, ring->rxd, size, rt2860_dma_map_addr, &ring->paddr, 0); if (error != 0) { device_printf(sc->sc_dev, "could not load desc DMA map\n"); goto fail; } error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 1, MCLBYTES, 0, NULL, NULL, &ring->data_dmat); if (error != 0) { device_printf(sc->sc_dev, "could not create data DMA tag\n"); goto fail; } for (i = 0; i < RT2860_RX_RING_COUNT; i++) { struct rt2860_rx_data *data = &ring->data[i]; struct rt2860_rxd *rxd = &ring->rxd[i]; error = bus_dmamap_create(ring->data_dmat, 0, &data->map); if (error != 0) { device_printf(sc->sc_dev, "could not create DMA map\n"); goto fail; } data->m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (data->m == NULL) { device_printf(sc->sc_dev, "could not allocate rx mbuf\n"); error = ENOMEM; goto fail; } error = bus_dmamap_load(ring->data_dmat, data->map, mtod(data->m, void *), MCLBYTES, rt2860_dma_map_addr, &physaddr, 0); if (error != 0) { device_printf(sc->sc_dev, "could not load rx buf DMA map"); goto fail; } rxd->sdp0 = htole32(physaddr); rxd->sdl0 = htole16(MCLBYTES); } bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_PREWRITE); return 0; fail: rt2860_free_rx_ring(sc, ring); return error; } void rt2860_reset_rx_ring(struct rt2860_softc *sc, struct rt2860_rx_ring *ring) { int i; for (i = 0; i < RT2860_RX_RING_COUNT; i++) ring->rxd[i].sdl0 &= ~htole16(RT2860_RX_DDONE); bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_PREWRITE); ring->cur = 0; } void rt2860_free_rx_ring(struct rt2860_softc *sc, struct rt2860_rx_ring *ring) { int i; if (ring->rxd != NULL) { bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(ring->desc_dmat, ring->desc_map); bus_dmamem_free(ring->desc_dmat, ring->rxd, ring->desc_map); } if (ring->desc_dmat != NULL) bus_dma_tag_destroy(ring->desc_dmat); for (i = 0; i < RT2860_RX_RING_COUNT; i++) { struct rt2860_rx_data *data = &ring->data[i]; if (data->m != NULL) { bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD); bus_dmamap_unload(ring->data_dmat, data->map); m_freem(data->m); } if (data->map != NULL) bus_dmamap_destroy(ring->data_dmat, data->map); } if (ring->data_dmat != NULL) bus_dma_tag_destroy(ring->data_dmat); } static void rt2860_updatestats(struct rt2860_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; /* * In IBSS or HostAP modes (when the hardware sends beacons), the * MAC can run into a livelock and start sending CTS-to-self frames * like crazy if protection is enabled. Fortunately, we can detect * when such a situation occurs and reset the MAC. */ if (ic->ic_curmode != IEEE80211_M_STA) { /* check if we're in a livelock situation.. */ uint32_t tmp = RAL_READ(sc, RT2860_DEBUG); if ((tmp & (1 << 29)) && (tmp & (1 << 7 | 1 << 5))) { /* ..and reset MAC/BBP for a while.. */ DPRINTF(("CTS-to-self livelock detected\n")); RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, RT2860_MAC_SRST); RAL_BARRIER_WRITE(sc); DELAY(1); RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, RT2860_MAC_RX_EN | RT2860_MAC_TX_EN); } } } static void rt2860_newassoc(struct ieee80211_node *ni, int isnew) { struct ieee80211com *ic = ni->ni_ic; struct rt2860_softc *sc = ic->ic_softc; uint8_t wcid; wcid = IEEE80211_AID(ni->ni_associd); if (isnew && ni->ni_associd != 0) { sc->wcid2ni[wcid] = ni; /* init WCID table entry */ RAL_WRITE_REGION_1(sc, RT2860_WCID_ENTRY(wcid), ni->ni_macaddr, IEEE80211_ADDR_LEN); } DPRINTF(("new assoc isnew=%d addr=%s WCID=%d\n", isnew, ether_sprintf(ni->ni_macaddr), wcid)); } static void rt2860_node_free(struct ieee80211_node *ni) { struct ieee80211com *ic = ni->ni_ic; struct rt2860_softc *sc = ic->ic_softc; uint8_t wcid; if (ni->ni_associd != 0) { wcid = IEEE80211_AID(ni->ni_associd); /* clear Rx WCID search table entry */ RAL_SET_REGION_4(sc, RT2860_WCID_ENTRY(wcid), 0, 2); } sc->sc_node_free(ni); } #ifdef IEEE80211_HT static int rt2860_ampdu_rx_start(struct ieee80211com *ic, struct ieee80211_node *ni, uint8_t tid) { struct rt2860_softc *sc = ic->ic_softc; uint8_t wcid = ((struct rt2860_node *)ni)->wcid; uint32_t tmp; /* update BA session mask */ tmp = RAL_READ(sc, RT2860_WCID_ENTRY(wcid) + 4); tmp |= (1 << tid) << 16; RAL_WRITE(sc, RT2860_WCID_ENTRY(wcid) + 4, tmp); return 0; } static void rt2860_ampdu_rx_stop(struct ieee80211com *ic, struct ieee80211_node *ni, uint8_t tid) { struct rt2860_softc *sc = ic->ic_softc; uint8_t wcid = ((struct rt2860_node *)ni)->wcid; uint32_t tmp; /* update BA session mask */ tmp = RAL_READ(sc, RT2860_WCID_ENTRY(wcid) + 4); tmp &= ~((1 << tid) << 16); RAL_WRITE(sc, RT2860_WCID_ENTRY(wcid) + 4, tmp); } #endif int rt2860_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) { struct rt2860_vap *rvp = RT2860_VAP(vap); struct ieee80211com *ic = vap->iv_ic; struct rt2860_softc *sc = ic->ic_softc; uint32_t tmp; int error; if (vap->iv_state == IEEE80211_S_RUN) { /* turn link LED off */ rt2860_set_leds(sc, RT2860_LED_RADIO); } if (nstate == IEEE80211_S_INIT && vap->iv_state == IEEE80211_S_RUN) { /* abort TSF synchronization */ tmp = RAL_READ(sc, RT2860_BCN_TIME_CFG); RAL_WRITE(sc, RT2860_BCN_TIME_CFG, tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN | RT2860_TBTT_TIMER_EN)); } rt2860_set_gp_timer(sc, 0); error = rvp->ral_newstate(vap, nstate, arg); if (error != 0) return (error); if (nstate == IEEE80211_S_RUN) { struct ieee80211_node *ni = vap->iv_bss; if (ic->ic_opmode != IEEE80211_M_MONITOR) { rt2860_enable_mrr(sc); rt2860_set_txpreamble(sc); rt2860_set_basicrates(sc, &ni->ni_rates); rt2860_set_bssid(sc, ni->ni_bssid); } if (vap->iv_opmode == IEEE80211_M_HOSTAP || vap->iv_opmode == IEEE80211_M_IBSS || vap->iv_opmode == IEEE80211_M_MBSS) { error = rt2860_setup_beacon(sc, vap); if (error != 0) return error; } if (ic->ic_opmode != IEEE80211_M_MONITOR) { rt2860_enable_tsf_sync(sc); rt2860_set_gp_timer(sc, 500); } /* turn link LED on */ rt2860_set_leds(sc, RT2860_LED_RADIO | (IEEE80211_IS_CHAN_2GHZ(ni->ni_chan) ? RT2860_LED_LINK_2GHZ : RT2860_LED_LINK_5GHZ)); } return error; } /* Read 16-bit from eFUSE ROM (>=RT3071 only.) */ static uint16_t rt3090_efuse_read_2(struct rt2860_softc *sc, uint16_t addr) { uint32_t tmp; uint16_t reg; int ntries; addr *= 2; /*- * Read one 16-byte block into registers EFUSE_DATA[0-3]: * DATA0: F E D C * DATA1: B A 9 8 * DATA2: 7 6 5 4 * DATA3: 3 2 1 0 */ tmp = RAL_READ(sc, RT3070_EFUSE_CTRL); tmp &= ~(RT3070_EFSROM_MODE_MASK | RT3070_EFSROM_AIN_MASK); tmp |= (addr & ~0xf) << RT3070_EFSROM_AIN_SHIFT | RT3070_EFSROM_KICK; RAL_WRITE(sc, RT3070_EFUSE_CTRL, tmp); for (ntries = 0; ntries < 500; ntries++) { tmp = RAL_READ(sc, RT3070_EFUSE_CTRL); if (!(tmp & RT3070_EFSROM_KICK)) break; DELAY(2); } if (ntries == 500) return 0xffff; if ((tmp & RT3070_EFUSE_AOUT_MASK) == RT3070_EFUSE_AOUT_MASK) return 0xffff; /* address not found */ /* determine to which 32-bit register our 16-bit word belongs */ reg = RT3070_EFUSE_DATA3 - (addr & 0xc); tmp = RAL_READ(sc, reg); return (addr & 2) ? tmp >> 16 : tmp & 0xffff; } /* * Read 16 bits at address 'addr' from the serial EEPROM (either 93C46, * 93C66 or 93C86). */ static uint16_t rt2860_eeprom_read_2(struct rt2860_softc *sc, uint16_t addr) { uint32_t tmp; uint16_t val; int n; /* clock C once before the first command */ RT2860_EEPROM_CTL(sc, 0); RT2860_EEPROM_CTL(sc, RT2860_S); RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_C); RT2860_EEPROM_CTL(sc, RT2860_S); /* write start bit (1) */ RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_D); RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_D | RT2860_C); /* write READ opcode (10) */ RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_D); RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_D | RT2860_C); RT2860_EEPROM_CTL(sc, RT2860_S); RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_C); /* write address (A5-A0 or A7-A0) */ n = ((RAL_READ(sc, RT2860_PCI_EECTRL) & 0x30) == 0) ? 5 : 7; for (; n >= 0; n--) { RT2860_EEPROM_CTL(sc, RT2860_S | (((addr >> n) & 1) << RT2860_SHIFT_D)); RT2860_EEPROM_CTL(sc, RT2860_S | (((addr >> n) & 1) << RT2860_SHIFT_D) | RT2860_C); } RT2860_EEPROM_CTL(sc, RT2860_S); /* read data Q15-Q0 */ val = 0; for (n = 15; n >= 0; n--) { RT2860_EEPROM_CTL(sc, RT2860_S | RT2860_C); tmp = RAL_READ(sc, RT2860_PCI_EECTRL); val |= ((tmp & RT2860_Q) >> RT2860_SHIFT_Q) << n; RT2860_EEPROM_CTL(sc, RT2860_S); } RT2860_EEPROM_CTL(sc, 0); /* clear Chip Select and clock C */ RT2860_EEPROM_CTL(sc, RT2860_S); RT2860_EEPROM_CTL(sc, 0); RT2860_EEPROM_CTL(sc, RT2860_C); return val; } static __inline uint16_t rt2860_srom_read(struct rt2860_softc *sc, uint8_t addr) { /* either eFUSE ROM or EEPROM */ return sc->sc_srom_read(sc, addr); } static void rt2860_intr_coherent(struct rt2860_softc *sc) { uint32_t tmp; /* DMA finds data coherent event when checking the DDONE bit */ DPRINTF(("Tx/Rx Coherent interrupt\n")); /* restart DMA engine */ tmp = RAL_READ(sc, RT2860_WPDMA_GLO_CFG); tmp &= ~(RT2860_TX_WB_DDONE | RT2860_RX_DMA_EN | RT2860_TX_DMA_EN); RAL_WRITE(sc, RT2860_WPDMA_GLO_CFG, tmp); (void)rt2860_txrx_enable(sc); } static void rt2860_drain_stats_fifo(struct rt2860_softc *sc) { struct ieee80211_node *ni; uint32_t stat; int retrycnt; uint8_t wcid, mcs, pid; /* drain Tx status FIFO (maxsize = 16) */ while ((stat = RAL_READ(sc, RT2860_TX_STAT_FIFO)) & RT2860_TXQ_VLD) { DPRINTFN(4, ("tx stat 0x%08x\n", stat)); wcid = (stat >> RT2860_TXQ_WCID_SHIFT) & 0xff; ni = sc->wcid2ni[wcid]; /* if no ACK was requested, no feedback is available */ if (!(stat & RT2860_TXQ_ACKREQ) || wcid == 0xff || ni == NULL) continue; /* update per-STA AMRR stats */ if (stat & RT2860_TXQ_OK) { /* * Check if there were retries, ie if the Tx success * rate is different from the requested rate. Note * that it works only because we do not allow rate * fallback from OFDM to CCK. */ mcs = (stat >> RT2860_TXQ_MCS_SHIFT) & 0x7f; pid = (stat >> RT2860_TXQ_PID_SHIFT) & 0xf; if (mcs + 1 != pid) retrycnt = 1; else retrycnt = 0; ieee80211_ratectl_tx_complete(ni->ni_vap, ni, IEEE80211_RATECTL_TX_SUCCESS, &retrycnt, NULL); } else { ieee80211_ratectl_tx_complete(ni->ni_vap, ni, IEEE80211_RATECTL_TX_FAILURE, &retrycnt, NULL); if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1); } } } static void rt2860_tx_intr(struct rt2860_softc *sc, int qid) { struct rt2860_tx_ring *ring = &sc->txq[qid]; uint32_t hw; rt2860_drain_stats_fifo(sc); hw = RAL_READ(sc, RT2860_TX_DTX_IDX(qid)); while (ring->next != hw) { struct rt2860_tx_data *data = ring->data[ring->next]; if (data != NULL) { bus_dmamap_sync(sc->txwi_dmat, data->map, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(sc->txwi_dmat, data->map); if (data->m->m_flags & M_TXCB) { ieee80211_process_callback(data->ni, data->m, 0); } ieee80211_tx_complete(data->ni, data->m, 0); data->ni = NULL; data->m = NULL; SLIST_INSERT_HEAD(&sc->data_pool, data, next); ring->data[ring->next] = NULL; } ring->queued--; ring->next = (ring->next + 1) % RT2860_TX_RING_COUNT; } sc->sc_tx_timer = 0; if (ring->queued < RT2860_TX_RING_COUNT) sc->qfullmsk &= ~(1 << qid); rt2860_start(sc); } /* * Return the Rx chain with the highest RSSI for a given frame. */ static __inline uint8_t rt2860_maxrssi_chain(struct rt2860_softc *sc, const struct rt2860_rxwi *rxwi) { uint8_t rxchain = 0; if (sc->nrxchains > 1) { if (rxwi->rssi[1] > rxwi->rssi[rxchain]) rxchain = 1; if (sc->nrxchains > 2) if (rxwi->rssi[2] > rxwi->rssi[rxchain]) rxchain = 2; } return rxchain; } static void rt2860_rx_intr(struct rt2860_softc *sc) { struct rt2860_rx_radiotap_header *tap; struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_frame *wh; struct ieee80211_node *ni; struct mbuf *m, *m1; bus_addr_t physaddr; uint32_t hw; uint16_t phy; uint8_t ant; int8_t rssi, nf; int error; hw = RAL_READ(sc, RT2860_FS_DRX_IDX) & 0xfff; while (sc->rxq.cur != hw) { struct rt2860_rx_data *data = &sc->rxq.data[sc->rxq.cur]; struct rt2860_rxd *rxd = &sc->rxq.rxd[sc->rxq.cur]; struct rt2860_rxwi *rxwi; bus_dmamap_sync(sc->rxq.desc_dmat, sc->rxq.desc_map, BUS_DMASYNC_POSTREAD); if (__predict_false(!(rxd->sdl0 & htole16(RT2860_RX_DDONE)))) { DPRINTF(("RXD DDONE bit not set!\n")); break; /* should not happen */ } if (__predict_false(rxd->flags & htole32(RT2860_RX_CRCERR | RT2860_RX_ICVERR))) { counter_u64_add(ic->ic_ierrors, 1); goto skip; } #ifdef HW_CRYPTO if (__predict_false(rxd->flags & htole32(RT2860_RX_MICERR))) { /* report MIC failures to net80211 for TKIP */ ic->ic_stats.is_rx_locmicfail++; ieee80211_michael_mic_failure(ic, 0/* XXX */); counter_u64_add(ic->ic_ierrors, 1); goto skip; } #endif m1 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (__predict_false(m1 == NULL)) { counter_u64_add(ic->ic_ierrors, 1); goto skip; } bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD); bus_dmamap_unload(sc->rxq.data_dmat, data->map); error = bus_dmamap_load(sc->rxq.data_dmat, data->map, mtod(m1, void *), MCLBYTES, rt2860_dma_map_addr, &physaddr, 0); if (__predict_false(error != 0)) { m_freem(m1); /* try to reload the old mbuf */ error = bus_dmamap_load(sc->rxq.data_dmat, data->map, mtod(data->m, void *), MCLBYTES, rt2860_dma_map_addr, &physaddr, 0); if (__predict_false(error != 0)) { panic("%s: could not load old rx mbuf", device_get_name(sc->sc_dev)); } /* physical address may have changed */ rxd->sdp0 = htole32(physaddr); counter_u64_add(ic->ic_ierrors, 1); goto skip; } /* * New mbuf successfully loaded, update Rx ring and continue * processing. */ m = data->m; data->m = m1; rxd->sdp0 = htole32(physaddr); rxwi = mtod(m, struct rt2860_rxwi *); /* finalize mbuf */ m->m_data = (caddr_t)(rxwi + 1); m->m_pkthdr.len = m->m_len = le16toh(rxwi->len) & 0xfff; wh = mtod(m, struct ieee80211_frame *); #ifdef HW_CRYPTO if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { /* frame is decrypted by hardware */ wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED; } #endif /* HW may insert 2 padding bytes after 802.11 header */ if (rxd->flags & htole32(RT2860_RX_L2PAD)) { u_int hdrlen = ieee80211_hdrsize(wh); ovbcopy(wh, (caddr_t)wh + 2, hdrlen); m->m_data += 2; wh = mtod(m, struct ieee80211_frame *); } ant = rt2860_maxrssi_chain(sc, rxwi); rssi = rt2860_rssi2dbm(sc, rxwi->rssi[ant], ant); nf = RT2860_NOISE_FLOOR; if (ieee80211_radiotap_active(ic)) { tap = &sc->sc_rxtap; tap->wr_flags = 0; tap->wr_antenna = ant; tap->wr_antsignal = nf + rssi; tap->wr_antnoise = nf; /* in case it can't be found below */ tap->wr_rate = 2; phy = le16toh(rxwi->phy); switch (phy & RT2860_PHY_MODE) { case RT2860_PHY_CCK: switch ((phy & RT2860_PHY_MCS) & ~RT2860_PHY_SHPRE) { case 0: tap->wr_rate = 2; break; case 1: tap->wr_rate = 4; break; case 2: tap->wr_rate = 11; break; case 3: tap->wr_rate = 22; break; } if (phy & RT2860_PHY_SHPRE) tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; break; case RT2860_PHY_OFDM: switch (phy & RT2860_PHY_MCS) { case 0: tap->wr_rate = 12; break; case 1: tap->wr_rate = 18; break; case 2: tap->wr_rate = 24; break; case 3: tap->wr_rate = 36; break; case 4: tap->wr_rate = 48; break; case 5: tap->wr_rate = 72; break; case 6: tap->wr_rate = 96; break; case 7: tap->wr_rate = 108; break; } break; } } RAL_UNLOCK(sc); wh = mtod(m, struct ieee80211_frame *); /* send the frame to the 802.11 layer */ ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh); if (ni != NULL) { (void)ieee80211_input(ni, m, rssi - nf, nf); ieee80211_free_node(ni); } else (void)ieee80211_input_all(ic, m, rssi - nf, nf); RAL_LOCK(sc); skip: rxd->sdl0 &= ~htole16(RT2860_RX_DDONE); bus_dmamap_sync(sc->rxq.desc_dmat, sc->rxq.desc_map, BUS_DMASYNC_PREWRITE); sc->rxq.cur = (sc->rxq.cur + 1) % RT2860_RX_RING_COUNT; } /* tell HW what we have processed */ RAL_WRITE(sc, RT2860_RX_CALC_IDX, (sc->rxq.cur - 1) % RT2860_RX_RING_COUNT); } static void rt2860_tbtt_intr(struct rt2860_softc *sc) { #if 0 struct ieee80211com *ic = &sc->sc_ic; #ifndef IEEE80211_STA_ONLY if (ic->ic_opmode == IEEE80211_M_HOSTAP) { /* one less beacon until next DTIM */ if (ic->ic_dtim_count == 0) ic->ic_dtim_count = ic->ic_dtim_period - 1; else ic->ic_dtim_count--; /* update dynamic parts of beacon */ rt2860_setup_beacon(sc); /* flush buffered multicast frames */ if (ic->ic_dtim_count == 0) ieee80211_notify_dtim(ic); } #endif /* check if protection mode has changed */ if ((sc->sc_ic_flags ^ ic->ic_flags) & IEEE80211_F_USEPROT) { rt2860_updateprot(sc); sc->sc_ic_flags = ic->ic_flags; } #endif } static void rt2860_gp_intr(struct rt2860_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); DPRINTFN(2, ("GP timeout state=%d\n", vap->iv_state)); if (vap->iv_state == IEEE80211_S_RUN) rt2860_updatestats(sc); } void rt2860_intr(void *arg) { struct rt2860_softc *sc = arg; uint32_t r; RAL_LOCK(sc); r = RAL_READ(sc, RT2860_INT_STATUS); if (__predict_false(r == 0xffffffff)) { RAL_UNLOCK(sc); return; /* device likely went away */ } if (r == 0) { RAL_UNLOCK(sc); return; /* not for us */ } /* acknowledge interrupts */ RAL_WRITE(sc, RT2860_INT_STATUS, r); if (r & RT2860_TX_RX_COHERENT) rt2860_intr_coherent(sc); if (r & RT2860_MAC_INT_2) /* TX status */ rt2860_drain_stats_fifo(sc); if (r & RT2860_TX_DONE_INT5) rt2860_tx_intr(sc, 5); if (r & RT2860_RX_DONE_INT) rt2860_rx_intr(sc); if (r & RT2860_TX_DONE_INT4) rt2860_tx_intr(sc, 4); if (r & RT2860_TX_DONE_INT3) rt2860_tx_intr(sc, 3); if (r & RT2860_TX_DONE_INT2) rt2860_tx_intr(sc, 2); if (r & RT2860_TX_DONE_INT1) rt2860_tx_intr(sc, 1); if (r & RT2860_TX_DONE_INT0) rt2860_tx_intr(sc, 0); if (r & RT2860_MAC_INT_0) /* TBTT */ rt2860_tbtt_intr(sc); if (r & RT2860_MAC_INT_3) /* Auto wakeup */ /* TBD wakeup */; if (r & RT2860_MAC_INT_4) /* GP timer */ rt2860_gp_intr(sc); RAL_UNLOCK(sc); } static int rt2860_tx(struct rt2860_softc *sc, struct mbuf *m, struct ieee80211_node *ni) { struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = ni->ni_vap; struct rt2860_tx_ring *ring; struct rt2860_tx_data *data; struct rt2860_txd *txd; struct rt2860_txwi *txwi; struct ieee80211_frame *wh; const struct ieee80211_txparam *tp; struct ieee80211_key *k; struct mbuf *m1; bus_dma_segment_t segs[RT2860_MAX_SCATTER]; bus_dma_segment_t *seg; u_int hdrlen; uint16_t qos, dur; uint8_t type, qsel, mcs, pid, tid, qid; int i, nsegs, ntxds, pad, rate, ridx, error; /* the data pool contains at least one element, pick the first */ data = SLIST_FIRST(&sc->data_pool); wh = mtod(m, struct ieee80211_frame *); if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { k = ieee80211_crypto_encap(ni, m); if (k == NULL) { m_freem(m); return ENOBUFS; } /* packet header may have moved, reset our local pointer */ wh = mtod(m, struct ieee80211_frame *); } hdrlen = ieee80211_anyhdrsize(wh); type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)]; if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { rate = tp->mcastrate; } else if (m->m_flags & M_EAPOL) { rate = tp->mgmtrate; } else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { rate = tp->ucastrate; } else { (void) ieee80211_ratectl_rate(ni, NULL, 0); rate = ni->ni_txrate; } rate &= IEEE80211_RATE_VAL; qid = M_WME_GETAC(m); if (IEEE80211_QOS_HAS_SEQ(wh)) { qos = ((const struct ieee80211_qosframe *)wh)->i_qos[0]; tid = qos & IEEE80211_QOS_TID; } else { qos = 0; tid = 0; } ring = &sc->txq[qid]; ridx = ieee80211_legacy_rate_lookup(ic->ic_rt, rate); /* get MCS code from rate index */ mcs = rt2860_rates[ridx].mcs; /* setup TX Wireless Information */ txwi = data->txwi; txwi->flags = 0; /* let HW generate seq numbers for non-QoS frames */ txwi->xflags = qos ? 0 : RT2860_TX_NSEQ; if (type == IEEE80211_FC0_TYPE_DATA) txwi->wcid = IEEE80211_AID(ni->ni_associd); else txwi->wcid = 0xff; txwi->len = htole16(m->m_pkthdr.len); if (rt2860_rates[ridx].phy == IEEE80211_T_DS) { txwi->phy = htole16(RT2860_PHY_CCK); if (ridx != RT2860_RIDX_CCK1 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) mcs |= RT2860_PHY_SHPRE; } else txwi->phy = htole16(RT2860_PHY_OFDM); txwi->phy |= htole16(mcs); /* * We store the MCS code into the driver-private PacketID field. * The PacketID is latched into TX_STAT_FIFO when Tx completes so * that we know at which initial rate the frame was transmitted. * We add 1 to the MCS code because setting the PacketID field to * 0 means that we don't want feedback in TX_STAT_FIFO. */ pid = (mcs + 1) & 0xf; txwi->len |= htole16(pid << RT2860_TX_PID_SHIFT); /* check if RTS/CTS or CTS-to-self protection is required */ if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && (m->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold || ((ic->ic_flags & IEEE80211_F_USEPROT) && rt2860_rates[ridx].phy == IEEE80211_T_OFDM))) txwi->txop = RT2860_TX_TXOP_HT; else txwi->txop = RT2860_TX_TXOP_BACKOFF; if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && (!qos || (qos & IEEE80211_QOS_ACKPOLICY) != IEEE80211_QOS_ACKPOLICY_NOACK)) { txwi->xflags |= RT2860_TX_ACK; if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) dur = rt2860_rates[ridx].sp_ack_dur; else dur = rt2860_rates[ridx].lp_ack_dur; *(uint16_t *)wh->i_dur = htole16(dur); } /* ask MAC to insert timestamp into probe responses */ if ((wh->i_fc[0] & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP)) /* NOTE: beacons do not pass through tx_data() */ txwi->flags |= RT2860_TX_TS; if (ieee80211_radiotap_active_vap(vap)) { struct rt2860_tx_radiotap_header *tap = &sc->sc_txtap; tap->wt_flags = 0; tap->wt_rate = rate; if (mcs & RT2860_PHY_SHPRE) tap->wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; ieee80211_radiotap_tx(vap, m); } pad = (hdrlen + 3) & ~3; /* copy and trim 802.11 header */ memcpy(txwi + 1, wh, hdrlen); m_adj(m, hdrlen); error = bus_dmamap_load_mbuf_sg(sc->txwi_dmat, data->map, m, segs, &nsegs, 0); if (__predict_false(error != 0 && error != EFBIG)) { device_printf(sc->sc_dev, "can't map mbuf (error %d)\n", error); m_freem(m); return error; } if (__predict_true(error == 0)) { /* determine how many TXDs are required */ ntxds = 1 + (nsegs / 2); if (ring->queued + ntxds >= RT2860_TX_RING_COUNT) { /* not enough free TXDs, force mbuf defrag */ bus_dmamap_unload(sc->txwi_dmat, data->map); error = EFBIG; } } if (__predict_false(error != 0)) { m1 = m_defrag(m, M_NOWAIT); if (m1 == NULL) { device_printf(sc->sc_dev, "could not defragment mbuf\n"); m_freem(m); return ENOBUFS; } m = m1; error = bus_dmamap_load_mbuf_sg(sc->txwi_dmat, data->map, m, segs, &nsegs, 0); if (__predict_false(error != 0)) { device_printf(sc->sc_dev, "can't map mbuf (error %d)\n", error); m_freem(m); return error; } /* determine how many TXDs are now required */ ntxds = 1 + (nsegs / 2); if (ring->queued + ntxds >= RT2860_TX_RING_COUNT) { /* this is a hopeless case, drop the mbuf! */ bus_dmamap_unload(sc->txwi_dmat, data->map); m_freem(m); return ENOBUFS; } } qsel = (qid < WME_NUM_AC) ? RT2860_TX_QSEL_EDCA : RT2860_TX_QSEL_MGMT; /* first segment is TXWI + 802.11 header */ txd = &ring->txd[ring->cur]; txd->sdp0 = htole32(data->paddr); txd->sdl0 = htole16(sizeof (struct rt2860_txwi) + pad); txd->flags = qsel; /* setup payload segments */ seg = &segs[0]; for (i = nsegs; i >= 2; i -= 2) { txd->sdp1 = htole32(seg->ds_addr); txd->sdl1 = htole16(seg->ds_len); seg++; ring->cur = (ring->cur + 1) % RT2860_TX_RING_COUNT; /* grab a new Tx descriptor */ txd = &ring->txd[ring->cur]; txd->sdp0 = htole32(seg->ds_addr); txd->sdl0 = htole16(seg->ds_len); txd->flags = qsel; seg++; } /* finalize last segment */ if (i > 0) { txd->sdp1 = htole32(seg->ds_addr); txd->sdl1 = htole16(seg->ds_len | RT2860_TX_LS1); } else { txd->sdl0 |= htole16(RT2860_TX_LS0); txd->sdl1 = 0; } /* remove from the free pool and link it into the SW Tx slot */ SLIST_REMOVE_HEAD(&sc->data_pool, next); data->m = m; data->ni = ni; ring->data[ring->cur] = data; bus_dmamap_sync(sc->txwi_dmat, sc->txwi_map, BUS_DMASYNC_PREWRITE); bus_dmamap_sync(sc->txwi_dmat, data->map, BUS_DMASYNC_PREWRITE); bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_PREWRITE); DPRINTFN(4, ("sending frame qid=%d wcid=%d nsegs=%d ridx=%d\n", qid, txwi->wcid, nsegs, ridx)); ring->cur = (ring->cur + 1) % RT2860_TX_RING_COUNT; ring->queued += ntxds; if (ring->queued >= RT2860_TX_RING_COUNT) sc->qfullmsk |= 1 << qid; /* kick Tx */ RAL_WRITE(sc, RT2860_TX_CTX_IDX(qid), ring->cur); return 0; } static int rt2860_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, const struct ieee80211_bpf_params *params) { struct ieee80211com *ic = ni->ni_ic; struct rt2860_softc *sc = ic->ic_softc; int error; RAL_LOCK(sc); /* prevent management frames from being sent if we're not ready */ if (!(sc->sc_flags & RT2860_RUNNING)) { RAL_UNLOCK(sc); m_freem(m); return ENETDOWN; } if (params == NULL) { /* * Legacy path; interpret frame contents to decide * precisely how to send the frame. */ error = rt2860_tx(sc, m, ni); } else { /* * Caller supplied explicit parameters to use in * sending the frame. */ error = rt2860_tx_raw(sc, m, ni, params); } sc->sc_tx_timer = 5; RAL_UNLOCK(sc); return error; } static int rt2860_tx_raw(struct rt2860_softc *sc, struct mbuf *m, struct ieee80211_node *ni, const struct ieee80211_bpf_params *params) { struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = ni->ni_vap; struct rt2860_tx_ring *ring; struct rt2860_tx_data *data; struct rt2860_txd *txd; struct rt2860_txwi *txwi; struct ieee80211_frame *wh; struct mbuf *m1; bus_dma_segment_t segs[RT2860_MAX_SCATTER]; bus_dma_segment_t *seg; u_int hdrlen; uint16_t dur; uint8_t type, qsel, mcs, pid, tid, qid; int i, nsegs, ntxds, pad, rate, ridx, error; /* the data pool contains at least one element, pick the first */ data = SLIST_FIRST(&sc->data_pool); wh = mtod(m, struct ieee80211_frame *); hdrlen = ieee80211_hdrsize(wh); type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; /* Choose a TX rate index. */ rate = params->ibp_rate0; ridx = ieee80211_legacy_rate_lookup(ic->ic_rt, rate & IEEE80211_RATE_VAL); if (ridx == (uint8_t)-1) { /* XXX fall back to mcast/mgmt rate? */ m_freem(m); return EINVAL; } qid = params->ibp_pri & 3; tid = 0; ring = &sc->txq[qid]; /* get MCS code from rate index */ mcs = rt2860_rates[ridx].mcs; /* setup TX Wireless Information */ txwi = data->txwi; txwi->flags = 0; /* let HW generate seq numbers for non-QoS frames */ txwi->xflags = params->ibp_pri & 3 ? 0 : RT2860_TX_NSEQ; txwi->wcid = 0xff; txwi->len = htole16(m->m_pkthdr.len); if (rt2860_rates[ridx].phy == IEEE80211_T_DS) { txwi->phy = htole16(RT2860_PHY_CCK); if (ridx != RT2860_RIDX_CCK1 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) mcs |= RT2860_PHY_SHPRE; } else txwi->phy = htole16(RT2860_PHY_OFDM); txwi->phy |= htole16(mcs); /* * We store the MCS code into the driver-private PacketID field. * The PacketID is latched into TX_STAT_FIFO when Tx completes so * that we know at which initial rate the frame was transmitted. * We add 1 to the MCS code because setting the PacketID field to * 0 means that we don't want feedback in TX_STAT_FIFO. */ pid = (mcs + 1) & 0xf; txwi->len |= htole16(pid << RT2860_TX_PID_SHIFT); /* check if RTS/CTS or CTS-to-self protection is required */ if (params->ibp_flags & IEEE80211_BPF_RTS || params->ibp_flags & IEEE80211_BPF_CTS) txwi->txop = RT2860_TX_TXOP_HT; else txwi->txop = RT2860_TX_TXOP_BACKOFF; if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0) { txwi->xflags |= RT2860_TX_ACK; if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) dur = rt2860_rates[ridx].sp_ack_dur; else dur = rt2860_rates[ridx].lp_ack_dur; *(uint16_t *)wh->i_dur = htole16(dur); } /* ask MAC to insert timestamp into probe responses */ if ((wh->i_fc[0] & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP)) /* NOTE: beacons do not pass through tx_data() */ txwi->flags |= RT2860_TX_TS; if (ieee80211_radiotap_active_vap(vap)) { struct rt2860_tx_radiotap_header *tap = &sc->sc_txtap; tap->wt_flags = 0; tap->wt_rate = rate; if (mcs & RT2860_PHY_SHPRE) tap->wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; ieee80211_radiotap_tx(vap, m); } pad = (hdrlen + 3) & ~3; /* copy and trim 802.11 header */ memcpy(txwi + 1, wh, hdrlen); m_adj(m, hdrlen); error = bus_dmamap_load_mbuf_sg(sc->txwi_dmat, data->map, m, segs, &nsegs, 0); if (__predict_false(error != 0 && error != EFBIG)) { device_printf(sc->sc_dev, "can't map mbuf (error %d)\n", error); m_freem(m); return error; } if (__predict_true(error == 0)) { /* determine how many TXDs are required */ ntxds = 1 + (nsegs / 2); if (ring->queued + ntxds >= RT2860_TX_RING_COUNT) { /* not enough free TXDs, force mbuf defrag */ bus_dmamap_unload(sc->txwi_dmat, data->map); error = EFBIG; } } if (__predict_false(error != 0)) { m1 = m_defrag(m, M_NOWAIT); if (m1 == NULL) { device_printf(sc->sc_dev, "could not defragment mbuf\n"); m_freem(m); return ENOBUFS; } m = m1; error = bus_dmamap_load_mbuf_sg(sc->txwi_dmat, data->map, m, segs, &nsegs, 0); if (__predict_false(error != 0)) { device_printf(sc->sc_dev, "can't map mbuf (error %d)\n", error); m_freem(m); return error; } /* determine how many TXDs are now required */ ntxds = 1 + (nsegs / 2); if (ring->queued + ntxds >= RT2860_TX_RING_COUNT) { /* this is a hopeless case, drop the mbuf! */ bus_dmamap_unload(sc->txwi_dmat, data->map); m_freem(m); return ENOBUFS; } } qsel = (qid < WME_NUM_AC) ? RT2860_TX_QSEL_EDCA : RT2860_TX_QSEL_MGMT; /* first segment is TXWI + 802.11 header */ txd = &ring->txd[ring->cur]; txd->sdp0 = htole32(data->paddr); txd->sdl0 = htole16(sizeof (struct rt2860_txwi) + pad); txd->flags = qsel; /* setup payload segments */ seg = &segs[0]; for (i = nsegs; i >= 2; i -= 2) { txd->sdp1 = htole32(seg->ds_addr); txd->sdl1 = htole16(seg->ds_len); seg++; ring->cur = (ring->cur + 1) % RT2860_TX_RING_COUNT; /* grab a new Tx descriptor */ txd = &ring->txd[ring->cur]; txd->sdp0 = htole32(seg->ds_addr); txd->sdl0 = htole16(seg->ds_len); txd->flags = qsel; seg++; } /* finalize last segment */ if (i > 0) { txd->sdp1 = htole32(seg->ds_addr); txd->sdl1 = htole16(seg->ds_len | RT2860_TX_LS1); } else { txd->sdl0 |= htole16(RT2860_TX_LS0); txd->sdl1 = 0; } /* remove from the free pool and link it into the SW Tx slot */ SLIST_REMOVE_HEAD(&sc->data_pool, next); data->m = m; data->ni = ni; ring->data[ring->cur] = data; bus_dmamap_sync(sc->txwi_dmat, sc->txwi_map, BUS_DMASYNC_PREWRITE); bus_dmamap_sync(sc->txwi_dmat, data->map, BUS_DMASYNC_PREWRITE); bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_PREWRITE); DPRINTFN(4, ("sending frame qid=%d wcid=%d nsegs=%d ridx=%d\n", qid, txwi->wcid, nsegs, ridx)); ring->cur = (ring->cur + 1) % RT2860_TX_RING_COUNT; ring->queued += ntxds; if (ring->queued >= RT2860_TX_RING_COUNT) sc->qfullmsk |= 1 << qid; /* kick Tx */ RAL_WRITE(sc, RT2860_TX_CTX_IDX(qid), ring->cur); return 0; } static int rt2860_transmit(struct ieee80211com *ic, struct mbuf *m) { struct rt2860_softc *sc = ic->ic_softc; int error; RAL_LOCK(sc); if ((sc->sc_flags & RT2860_RUNNING) == 0) { RAL_UNLOCK(sc); return (ENXIO); } error = mbufq_enqueue(&sc->sc_snd, m); if (error) { RAL_UNLOCK(sc); return (error); } rt2860_start(sc); RAL_UNLOCK(sc); return (0); } static void rt2860_start(struct rt2860_softc *sc) { struct ieee80211_node *ni; struct mbuf *m; RAL_LOCK_ASSERT(sc); if ((sc->sc_flags & RT2860_RUNNING) == 0) return; while (!SLIST_EMPTY(&sc->data_pool) && sc->qfullmsk == 0 && (m = mbufq_dequeue(&sc->sc_snd)) != NULL) { ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; if (rt2860_tx(sc, m, ni) != 0) { if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1); ieee80211_free_node(ni); continue; } sc->sc_tx_timer = 5; } } static void rt2860_watchdog(void *arg) { struct rt2860_softc *sc = arg; RAL_LOCK_ASSERT(sc); KASSERT(sc->sc_flags & RT2860_RUNNING, ("not running")); if (sc->sc_invalid) /* card ejected */ return; if (sc->sc_tx_timer > 0 && --sc->sc_tx_timer == 0) { device_printf(sc->sc_dev, "device timeout\n"); rt2860_stop_locked(sc); rt2860_init_locked(sc); counter_u64_add(sc->sc_ic.ic_oerrors, 1); return; } callout_reset(&sc->watchdog_ch, hz, rt2860_watchdog, sc); } static void rt2860_parent(struct ieee80211com *ic) { struct rt2860_softc *sc = ic->ic_softc; int startall = 0; RAL_LOCK(sc); if (ic->ic_nrunning> 0) { if (!(sc->sc_flags & RT2860_RUNNING)) { rt2860_init_locked(sc); startall = 1; } else rt2860_update_promisc(ic); } else if (sc->sc_flags & RT2860_RUNNING) rt2860_stop_locked(sc); RAL_UNLOCK(sc); if (startall) ieee80211_start_all(ic); } /* * Reading and writing from/to the BBP is different from RT2560 and RT2661. * We access the BBP through the 8051 microcontroller unit which means that * the microcode must be loaded first. */ void rt2860_mcu_bbp_write(struct rt2860_softc *sc, uint8_t reg, uint8_t val) { int ntries; for (ntries = 0; ntries < 100; ntries++) { if (!(RAL_READ(sc, RT2860_H2M_BBPAGENT) & RT2860_BBP_CSR_KICK)) break; DELAY(1); } if (ntries == 100) { device_printf(sc->sc_dev, "could not write to BBP through MCU\n"); return; } RAL_WRITE(sc, RT2860_H2M_BBPAGENT, RT2860_BBP_RW_PARALLEL | RT2860_BBP_CSR_KICK | reg << 8 | val); RAL_BARRIER_WRITE(sc); rt2860_mcu_cmd(sc, RT2860_MCU_CMD_BBP, 0, 0); DELAY(1000); } uint8_t rt2860_mcu_bbp_read(struct rt2860_softc *sc, uint8_t reg) { uint32_t val; int ntries; for (ntries = 0; ntries < 100; ntries++) { if (!(RAL_READ(sc, RT2860_H2M_BBPAGENT) & RT2860_BBP_CSR_KICK)) break; DELAY(1); } if (ntries == 100) { device_printf(sc->sc_dev, "could not read from BBP through MCU\n"); return 0; } RAL_WRITE(sc, RT2860_H2M_BBPAGENT, RT2860_BBP_RW_PARALLEL | RT2860_BBP_CSR_KICK | RT2860_BBP_CSR_READ | reg << 8); RAL_BARRIER_WRITE(sc); rt2860_mcu_cmd(sc, RT2860_MCU_CMD_BBP, 0, 0); DELAY(1000); for (ntries = 0; ntries < 100; ntries++) { val = RAL_READ(sc, RT2860_H2M_BBPAGENT); if (!(val & RT2860_BBP_CSR_KICK)) return val & 0xff; DELAY(1); } device_printf(sc->sc_dev, "could not read from BBP through MCU\n"); return 0; } /* * Write to one of the 4 programmable 24-bit RF registers. */ static void rt2860_rf_write(struct rt2860_softc *sc, uint8_t reg, uint32_t val) { uint32_t tmp; int ntries; for (ntries = 0; ntries < 100; ntries++) { if (!(RAL_READ(sc, RT2860_RF_CSR_CFG0) & RT2860_RF_REG_CTRL)) break; DELAY(1); } if (ntries == 100) { device_printf(sc->sc_dev, "could not write to RF\n"); return; } /* RF registers are 24-bit on the RT2860 */ tmp = RT2860_RF_REG_CTRL | 24 << RT2860_RF_REG_WIDTH_SHIFT | (val & 0x3fffff) << 2 | (reg & 3); RAL_WRITE(sc, RT2860_RF_CSR_CFG0, tmp); } static uint8_t rt3090_rf_read(struct rt2860_softc *sc, uint8_t reg) { uint32_t tmp; int ntries; for (ntries = 0; ntries < 100; ntries++) { if (!(RAL_READ(sc, RT3070_RF_CSR_CFG) & RT3070_RF_KICK)) break; DELAY(1); } if (ntries == 100) { device_printf(sc->sc_dev, "could not read RF register\n"); return 0xff; } tmp = RT3070_RF_KICK | reg << 8; RAL_WRITE(sc, RT3070_RF_CSR_CFG, tmp); for (ntries = 0; ntries < 100; ntries++) { tmp = RAL_READ(sc, RT3070_RF_CSR_CFG); if (!(tmp & RT3070_RF_KICK)) break; DELAY(1); } if (ntries == 100) { device_printf(sc->sc_dev, "could not read RF register\n"); return 0xff; } return tmp & 0xff; } void rt3090_rf_write(struct rt2860_softc *sc, uint8_t reg, uint8_t val) { uint32_t tmp; int ntries; for (ntries = 0; ntries < 10; ntries++) { if (!(RAL_READ(sc, RT3070_RF_CSR_CFG) & RT3070_RF_KICK)) break; DELAY(10); } if (ntries == 10) { device_printf(sc->sc_dev, "could not write to RF\n"); return; } tmp = RT3070_RF_WRITE | RT3070_RF_KICK | reg << 8 | val; RAL_WRITE(sc, RT3070_RF_CSR_CFG, tmp); } /* * Send a command to the 8051 microcontroller unit. */ int rt2860_mcu_cmd(struct rt2860_softc *sc, uint8_t cmd, uint16_t arg, int wait) { int slot, ntries; uint32_t tmp; uint8_t cid; for (ntries = 0; ntries < 100; ntries++) { if (!(RAL_READ(sc, RT2860_H2M_MAILBOX) & RT2860_H2M_BUSY)) break; DELAY(2); } if (ntries == 100) return EIO; cid = wait ? cmd : RT2860_TOKEN_NO_INTR; RAL_WRITE(sc, RT2860_H2M_MAILBOX, RT2860_H2M_BUSY | cid << 16 | arg); RAL_BARRIER_WRITE(sc); RAL_WRITE(sc, RT2860_HOST_CMD, cmd); if (!wait) return 0; /* wait for the command to complete */ for (ntries = 0; ntries < 200; ntries++) { tmp = RAL_READ(sc, RT2860_H2M_MAILBOX_CID); /* find the command slot */ for (slot = 0; slot < 4; slot++, tmp >>= 8) if ((tmp & 0xff) == cid) break; if (slot < 4) break; DELAY(100); } if (ntries == 200) { /* clear command and status */ RAL_WRITE(sc, RT2860_H2M_MAILBOX_STATUS, 0xffffffff); RAL_WRITE(sc, RT2860_H2M_MAILBOX_CID, 0xffffffff); return ETIMEDOUT; } /* get command status (1 means success) */ tmp = RAL_READ(sc, RT2860_H2M_MAILBOX_STATUS); tmp = (tmp >> (slot * 8)) & 0xff; DPRINTF(("MCU command=0x%02x slot=%d status=0x%02x\n", cmd, slot, tmp)); /* clear command and status */ RAL_WRITE(sc, RT2860_H2M_MAILBOX_STATUS, 0xffffffff); RAL_WRITE(sc, RT2860_H2M_MAILBOX_CID, 0xffffffff); return (tmp == 1) ? 0 : EIO; } static void rt2860_enable_mrr(struct rt2860_softc *sc) { #define CCK(mcs) (mcs) #define OFDM(mcs) (1 << 3 | (mcs)) RAL_WRITE(sc, RT2860_LG_FBK_CFG0, OFDM(6) << 28 | /* 54->48 */ OFDM(5) << 24 | /* 48->36 */ OFDM(4) << 20 | /* 36->24 */ OFDM(3) << 16 | /* 24->18 */ OFDM(2) << 12 | /* 18->12 */ OFDM(1) << 8 | /* 12-> 9 */ OFDM(0) << 4 | /* 9-> 6 */ OFDM(0)); /* 6-> 6 */ RAL_WRITE(sc, RT2860_LG_FBK_CFG1, CCK(2) << 12 | /* 11->5.5 */ CCK(1) << 8 | /* 5.5-> 2 */ CCK(0) << 4 | /* 2-> 1 */ CCK(0)); /* 1-> 1 */ #undef OFDM #undef CCK } static void rt2860_set_txpreamble(struct rt2860_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; uint32_t tmp; tmp = RAL_READ(sc, RT2860_AUTO_RSP_CFG); tmp &= ~RT2860_CCK_SHORT_EN; if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) tmp |= RT2860_CCK_SHORT_EN; RAL_WRITE(sc, RT2860_AUTO_RSP_CFG, tmp); } void rt2860_set_basicrates(struct rt2860_softc *sc, const struct ieee80211_rateset *rs) { struct ieee80211com *ic = &sc->sc_ic; uint32_t mask = 0; uint8_t rate; int i; for (i = 0; i < rs->rs_nrates; i++) { rate = rs->rs_rates[i]; if (!(rate & IEEE80211_RATE_BASIC)) continue; mask |= 1 << ieee80211_legacy_rate_lookup(ic->ic_rt, IEEE80211_RV(rate)); } RAL_WRITE(sc, RT2860_LEGACY_BASIC_RATE, mask); } static void rt2860_scan_start(struct ieee80211com *ic) { struct rt2860_softc *sc = ic->ic_softc; uint32_t tmp; tmp = RAL_READ(sc, RT2860_BCN_TIME_CFG); RAL_WRITE(sc, RT2860_BCN_TIME_CFG, tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN | RT2860_TBTT_TIMER_EN)); rt2860_set_gp_timer(sc, 0); } static void rt2860_scan_end(struct ieee80211com *ic) { struct rt2860_softc *sc = ic->ic_softc; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); if (vap->iv_state == IEEE80211_S_RUN) { rt2860_enable_tsf_sync(sc); rt2860_set_gp_timer(sc, 500); } } static void rt2860_set_channel(struct ieee80211com *ic) { struct rt2860_softc *sc = ic->ic_softc; RAL_LOCK(sc); rt2860_switch_chan(sc, ic->ic_curchan); RAL_UNLOCK(sc); } static void rt2860_select_chan_group(struct rt2860_softc *sc, int group) { uint32_t tmp; uint8_t agc; rt2860_mcu_bbp_write(sc, 62, 0x37 - sc->lna[group]); rt2860_mcu_bbp_write(sc, 63, 0x37 - sc->lna[group]); rt2860_mcu_bbp_write(sc, 64, 0x37 - sc->lna[group]); rt2860_mcu_bbp_write(sc, 86, 0x00); if (group == 0) { if (sc->ext_2ghz_lna) { rt2860_mcu_bbp_write(sc, 82, 0x62); rt2860_mcu_bbp_write(sc, 75, 0x46); } else { rt2860_mcu_bbp_write(sc, 82, 0x84); rt2860_mcu_bbp_write(sc, 75, 0x50); } } else { if (sc->ext_5ghz_lna) { rt2860_mcu_bbp_write(sc, 82, 0xf2); rt2860_mcu_bbp_write(sc, 75, 0x46); } else { rt2860_mcu_bbp_write(sc, 82, 0xf2); rt2860_mcu_bbp_write(sc, 75, 0x50); } } tmp = RAL_READ(sc, RT2860_TX_BAND_CFG); tmp &= ~(RT2860_5G_BAND_SEL_N | RT2860_5G_BAND_SEL_P); tmp |= (group == 0) ? RT2860_5G_BAND_SEL_N : RT2860_5G_BAND_SEL_P; RAL_WRITE(sc, RT2860_TX_BAND_CFG, tmp); /* enable appropriate Power Amplifiers and Low Noise Amplifiers */ tmp = RT2860_RFTR_EN | RT2860_TRSW_EN | RT2860_LNA_PE0_EN; if (sc->nrxchains > 1) tmp |= RT2860_LNA_PE1_EN; if (sc->mac_ver == 0x3593 && sc->nrxchains > 2) tmp |= RT3593_LNA_PE2_EN; if (group == 0) { /* 2GHz */ tmp |= RT2860_PA_PE_G0_EN; if (sc->ntxchains > 1) tmp |= RT2860_PA_PE_G1_EN; if (sc->mac_ver == 0x3593 && sc->ntxchains > 2) tmp |= RT3593_PA_PE_G2_EN; } else { /* 5GHz */ tmp |= RT2860_PA_PE_A0_EN; if (sc->ntxchains > 1) tmp |= RT2860_PA_PE_A1_EN; if (sc->mac_ver == 0x3593 && sc->ntxchains > 2) tmp |= RT3593_PA_PE_A2_EN; } RAL_WRITE(sc, RT2860_TX_PIN_CFG, tmp); if (sc->mac_ver == 0x3593) { tmp = RAL_READ(sc, RT2860_GPIO_CTRL); if (sc->sc_flags & RT2860_PCIE) { tmp &= ~0x01010000; if (group == 0) tmp |= 0x00010000; } else { tmp &= ~0x00008080; if (group == 0) tmp |= 0x00000080; } tmp = (tmp & ~0x00001000) | 0x00000010; RAL_WRITE(sc, RT2860_GPIO_CTRL, tmp); } /* set initial AGC value */ if (group == 0) { /* 2GHz band */ if (sc->mac_ver >= 0x3071) agc = 0x1c + sc->lna[0] * 2; else agc = 0x2e + sc->lna[0]; } else { /* 5GHz band */ agc = 0x32 + (sc->lna[group] * 5) / 3; } rt2860_mcu_bbp_write(sc, 66, agc); DELAY(1000); } static void rt2860_set_chan(struct rt2860_softc *sc, u_int chan) { const struct rfprog *rfprog = rt2860_rf2850; uint32_t r2, r3, r4; int8_t txpow1, txpow2; u_int i; /* find the settings for this channel (we know it exists) */ for (i = 0; rfprog[i].chan != chan; i++); r2 = rfprog[i].r2; if (sc->ntxchains == 1) r2 |= 1 << 12; /* 1T: disable Tx chain 2 */ if (sc->nrxchains == 1) r2 |= 1 << 15 | 1 << 4; /* 1R: disable Rx chains 2 & 3 */ else if (sc->nrxchains == 2) r2 |= 1 << 4; /* 2R: disable Rx chain 3 */ /* use Tx power values from EEPROM */ txpow1 = sc->txpow1[i]; txpow2 = sc->txpow2[i]; if (chan > 14) { if (txpow1 >= 0) txpow1 = txpow1 << 1 | 1; else txpow1 = (7 + txpow1) << 1; if (txpow2 >= 0) txpow2 = txpow2 << 1 | 1; else txpow2 = (7 + txpow2) << 1; } r3 = rfprog[i].r3 | txpow1 << 7; r4 = rfprog[i].r4 | sc->freq << 13 | txpow2 << 4; rt2860_rf_write(sc, RT2860_RF1, rfprog[i].r1); rt2860_rf_write(sc, RT2860_RF2, r2); rt2860_rf_write(sc, RT2860_RF3, r3); rt2860_rf_write(sc, RT2860_RF4, r4); DELAY(200); rt2860_rf_write(sc, RT2860_RF1, rfprog[i].r1); rt2860_rf_write(sc, RT2860_RF2, r2); rt2860_rf_write(sc, RT2860_RF3, r3 | 1); rt2860_rf_write(sc, RT2860_RF4, r4); DELAY(200); rt2860_rf_write(sc, RT2860_RF1, rfprog[i].r1); rt2860_rf_write(sc, RT2860_RF2, r2); rt2860_rf_write(sc, RT2860_RF3, r3); rt2860_rf_write(sc, RT2860_RF4, r4); } static void rt3090_set_chan(struct rt2860_softc *sc, u_int chan) { int8_t txpow1, txpow2; uint8_t rf; int i; /* RT3090 is 2GHz only */ KASSERT(chan >= 1 && chan <= 14, ("chan %d not support", chan)); /* find the settings for this channel (we know it exists) */ for (i = 0; rt2860_rf2850[i].chan != chan; i++); /* use Tx power values from EEPROM */ txpow1 = sc->txpow1[i]; txpow2 = sc->txpow2[i]; rt3090_rf_write(sc, 2, rt3090_freqs[i].n); rf = rt3090_rf_read(sc, 3); rf = (rf & ~0x0f) | rt3090_freqs[i].k; rt3090_rf_write(sc, 3, rf); rf = rt3090_rf_read(sc, 6); rf = (rf & ~0x03) | rt3090_freqs[i].r; rt3090_rf_write(sc, 6, rf); /* set Tx0 power */ rf = rt3090_rf_read(sc, 12); rf = (rf & ~0x1f) | txpow1; rt3090_rf_write(sc, 12, rf); /* set Tx1 power */ rf = rt3090_rf_read(sc, 13); rf = (rf & ~0x1f) | txpow2; rt3090_rf_write(sc, 13, rf); rf = rt3090_rf_read(sc, 1); rf &= ~0xfc; if (sc->ntxchains == 1) rf |= RT3070_TX1_PD | RT3070_TX2_PD; else if (sc->ntxchains == 2) rf |= RT3070_TX2_PD; if (sc->nrxchains == 1) rf |= RT3070_RX1_PD | RT3070_RX2_PD; else if (sc->nrxchains == 2) rf |= RT3070_RX2_PD; rt3090_rf_write(sc, 1, rf); /* set RF offset */ rf = rt3090_rf_read(sc, 23); rf = (rf & ~0x7f) | sc->freq; rt3090_rf_write(sc, 23, rf); /* program RF filter */ rf = rt3090_rf_read(sc, 24); /* Tx */ rf = (rf & ~0x3f) | sc->rf24_20mhz; rt3090_rf_write(sc, 24, rf); rf = rt3090_rf_read(sc, 31); /* Rx */ rf = (rf & ~0x3f) | sc->rf24_20mhz; rt3090_rf_write(sc, 31, rf); /* enable RF tuning */ rf = rt3090_rf_read(sc, 7); rt3090_rf_write(sc, 7, rf | RT3070_TUNE); } static void rt5390_set_chan(struct rt2860_softc *sc, u_int chan) { uint8_t h20mhz, rf, tmp; int8_t txpow1, txpow2; int i; /* RT5390 is 2GHz only */ KASSERT(chan >= 1 && chan <= 14, ("chan %d not support", chan)); /* find the settings for this channel (we know it exists) */ for (i = 0; rt2860_rf2850[i].chan != chan; i++); /* use Tx power values from EEPROM */ txpow1 = sc->txpow1[i]; txpow2 = sc->txpow2[i]; rt3090_rf_write(sc, 8, rt3090_freqs[i].n); rt3090_rf_write(sc, 9, rt3090_freqs[i].k & 0x0f); rf = rt3090_rf_read(sc, 11); rf = (rf & ~0x03) | (rt3090_freqs[i].r & 0x03); rt3090_rf_write(sc, 11, rf); rf = rt3090_rf_read(sc, 49); rf = (rf & ~0x3f) | (txpow1 & 0x3f); /* the valid range of the RF R49 is 0x00~0x27 */ if ((rf & 0x3f) > 0x27) rf = (rf & ~0x3f) | 0x27; rt3090_rf_write(sc, 49, rf); if (sc->mac_ver == 0x5392) { rf = rt3090_rf_read(sc, 50); rf = (rf & ~0x3f) | (txpow2 & 0x3f); /* the valid range of the RF R50 is 0x00~0x27 */ if ((rf & 0x3f) > 0x27) rf = (rf & ~0x3f) | 0x27; rt3090_rf_write(sc, 50, rf); } rf = rt3090_rf_read(sc, 1); rf |= RT3070_RF_BLOCK | RT3070_PLL_PD | RT3070_RX0_PD | RT3070_TX0_PD; if (sc->mac_ver == 0x5392) rf |= RT3070_RX1_PD | RT3070_TX1_PD; rt3090_rf_write(sc, 1, rf); rf = rt3090_rf_read(sc, 2); rt3090_rf_write(sc, 2, rf | RT3593_RESCAL); DELAY(1000); rt3090_rf_write(sc, 2, rf & ~RT3593_RESCAL); rf = rt3090_rf_read(sc, 17); tmp = rf; rf = (rf & ~0x7f) | (sc->freq & 0x7f); rf = MIN(rf, 0x5f); if (tmp != rf) rt2860_mcu_cmd(sc, 0x74, (tmp << 8 ) | rf, 0); if (sc->mac_ver == 0x5390) { if (chan <= 4) rf = 0x73; else if (chan >= 5 && chan <= 6) rf = 0x63; else if (chan >= 7 && chan <= 10) rf = 0x53; else rf = 43; rt3090_rf_write(sc, 55, rf); if (chan == 1) rf = 0x0c; else if (chan == 2) rf = 0x0b; else if (chan == 3) rf = 0x0a; else if (chan >= 4 && chan <= 6) rf = 0x09; else if (chan >= 7 && chan <= 12) rf = 0x08; else if (chan == 13) rf = 0x07; else rf = 0x06; rt3090_rf_write(sc, 59, rf); } /* Tx/Rx h20M */ h20mhz = (sc->rf24_20mhz & 0x20) >> 5; rf = rt3090_rf_read(sc, 30); rf = (rf & ~0x06) | (h20mhz << 1) | (h20mhz << 2); rt3090_rf_write(sc, 30, rf); /* Rx BB filter VCM */ rf = rt3090_rf_read(sc, 30); rf = (rf & ~0x18) | 0x10; rt3090_rf_write(sc, 30, rf); /* Initiate VCO calibration. */ rf = rt3090_rf_read(sc, 3); rf |= RT3593_VCOCAL; rt3090_rf_write(sc, 3, rf); } static int rt3090_rf_init(struct rt2860_softc *sc) { uint32_t tmp; uint8_t rf, bbp; int i; rf = rt3090_rf_read(sc, 30); /* toggle RF R30 bit 7 */ rt3090_rf_write(sc, 30, rf | 0x80); DELAY(1000); rt3090_rf_write(sc, 30, rf & ~0x80); tmp = RAL_READ(sc, RT3070_LDO_CFG0); tmp &= ~0x1f000000; if (sc->patch_dac && sc->mac_rev < 0x0211) tmp |= 0x0d000000; /* 1.35V */ else tmp |= 0x01000000; /* 1.2V */ RAL_WRITE(sc, RT3070_LDO_CFG0, tmp); /* patch LNA_PE_G1 */ tmp = RAL_READ(sc, RT3070_GPIO_SWITCH); RAL_WRITE(sc, RT3070_GPIO_SWITCH, tmp & ~0x20); /* initialize RF registers to default value */ for (i = 0; i < nitems(rt3090_def_rf); i++) { rt3090_rf_write(sc, rt3090_def_rf[i].reg, rt3090_def_rf[i].val); } /* select 20MHz bandwidth */ rt3090_rf_write(sc, 31, 0x14); rf = rt3090_rf_read(sc, 6); rt3090_rf_write(sc, 6, rf | 0x40); if (sc->mac_ver != 0x3593) { /* calibrate filter for 20MHz bandwidth */ sc->rf24_20mhz = 0x1f; /* default value */ rt3090_filter_calib(sc, 0x07, 0x16, &sc->rf24_20mhz); /* select 40MHz bandwidth */ bbp = rt2860_mcu_bbp_read(sc, 4); rt2860_mcu_bbp_write(sc, 4, (bbp & ~0x08) | 0x10); rf = rt3090_rf_read(sc, 31); rt3090_rf_write(sc, 31, rf | 0x20); /* calibrate filter for 40MHz bandwidth */ sc->rf24_40mhz = 0x2f; /* default value */ rt3090_filter_calib(sc, 0x27, 0x19, &sc->rf24_40mhz); /* go back to 20MHz bandwidth */ bbp = rt2860_mcu_bbp_read(sc, 4); rt2860_mcu_bbp_write(sc, 4, bbp & ~0x18); } if (sc->mac_rev < 0x0211) rt3090_rf_write(sc, 27, 0x03); tmp = RAL_READ(sc, RT3070_OPT_14); RAL_WRITE(sc, RT3070_OPT_14, tmp | 1); if (sc->rf_rev == RT3070_RF_3020) rt3090_set_rx_antenna(sc, 0); bbp = rt2860_mcu_bbp_read(sc, 138); if (sc->mac_ver == 0x3593) { if (sc->ntxchains == 1) bbp |= 0x60; /* turn off DAC1 and DAC2 */ else if (sc->ntxchains == 2) bbp |= 0x40; /* turn off DAC2 */ if (sc->nrxchains == 1) bbp &= ~0x06; /* turn off ADC1 and ADC2 */ else if (sc->nrxchains == 2) bbp &= ~0x04; /* turn off ADC2 */ } else { if (sc->ntxchains == 1) bbp |= 0x20; /* turn off DAC1 */ if (sc->nrxchains == 1) bbp &= ~0x02; /* turn off ADC1 */ } rt2860_mcu_bbp_write(sc, 138, bbp); rf = rt3090_rf_read(sc, 1); rf &= ~(RT3070_RX0_PD | RT3070_TX0_PD); rf |= RT3070_RF_BLOCK | RT3070_RX1_PD | RT3070_TX1_PD; rt3090_rf_write(sc, 1, rf); rf = rt3090_rf_read(sc, 15); rt3090_rf_write(sc, 15, rf & ~RT3070_TX_LO2); rf = rt3090_rf_read(sc, 17); rf &= ~RT3070_TX_LO1; if (sc->mac_rev >= 0x0211 && !sc->ext_2ghz_lna) rf |= 0x20; /* fix for long range Rx issue */ if (sc->txmixgain_2ghz >= 2) rf = (rf & ~0x7) | sc->txmixgain_2ghz; rt3090_rf_write(sc, 17, rf); rf = rt3090_rf_read(sc, 20); rt3090_rf_write(sc, 20, rf & ~RT3070_RX_LO1); rf = rt3090_rf_read(sc, 21); rt3090_rf_write(sc, 21, rf & ~RT3070_RX_LO2); return (0); } static void rt5390_rf_init(struct rt2860_softc *sc) { uint8_t rf, bbp; int i; rf = rt3090_rf_read(sc, 2); /* Toggle RF R2 bit 7. */ rt3090_rf_write(sc, 2, rf | RT3593_RESCAL); DELAY(1000); rt3090_rf_write(sc, 2, rf & ~RT3593_RESCAL); /* Initialize RF registers to default value. */ if (sc->mac_ver == 0x5392) { for (i = 0; i < nitems(rt5392_def_rf); i++) { rt3090_rf_write(sc, rt5392_def_rf[i].reg, rt5392_def_rf[i].val); } } else { for (i = 0; i < nitems(rt5390_def_rf); i++) { rt3090_rf_write(sc, rt5390_def_rf[i].reg, rt5390_def_rf[i].val); } } sc->rf24_20mhz = 0x1f; sc->rf24_40mhz = 0x2f; if (sc->mac_rev < 0x0211) rt3090_rf_write(sc, 27, 0x03); /* Set led open drain enable. */ RAL_WRITE(sc, RT3070_OPT_14, RAL_READ(sc, RT3070_OPT_14) | 1); RAL_WRITE(sc, RT2860_TX_SW_CFG1, 0); RAL_WRITE(sc, RT2860_TX_SW_CFG2, 0); if (sc->mac_ver == 0x5390) rt3090_set_rx_antenna(sc, 0); /* Patch RSSI inaccurate issue. */ rt2860_mcu_bbp_write(sc, 79, 0x13); rt2860_mcu_bbp_write(sc, 80, 0x05); rt2860_mcu_bbp_write(sc, 81, 0x33); /* Enable DC filter. */ if (sc->mac_rev >= 0x0211) rt2860_mcu_bbp_write(sc, 103, 0xc0); bbp = rt2860_mcu_bbp_read(sc, 138); if (sc->ntxchains == 1) bbp |= 0x20; /* Turn off DAC1. */ if (sc->nrxchains == 1) bbp &= ~0x02; /* Turn off ADC1. */ rt2860_mcu_bbp_write(sc, 138, bbp); /* Enable RX LO1 and LO2. */ rt3090_rf_write(sc, 38, rt3090_rf_read(sc, 38) & ~RT5390_RX_LO1); rt3090_rf_write(sc, 39, rt3090_rf_read(sc, 39) & ~RT5390_RX_LO2); /* Avoid data lost and CRC error. */ rt2860_mcu_bbp_write(sc, 4, rt2860_mcu_bbp_read(sc, 4) | RT5390_MAC_IF_CTRL); rf = rt3090_rf_read(sc, 30); rf = (rf & ~0x18) | 0x10; rt3090_rf_write(sc, 30, rf); } static void rt3090_rf_wakeup(struct rt2860_softc *sc) { uint32_t tmp; uint8_t rf; if (sc->mac_ver == 0x3593) { /* enable VCO */ rf = rt3090_rf_read(sc, 1); rt3090_rf_write(sc, 1, rf | RT3593_VCO); /* initiate VCO calibration */ rf = rt3090_rf_read(sc, 3); rt3090_rf_write(sc, 3, rf | RT3593_VCOCAL); /* enable VCO bias current control */ rf = rt3090_rf_read(sc, 6); rt3090_rf_write(sc, 6, rf | RT3593_VCO_IC); /* initiate res calibration */ rf = rt3090_rf_read(sc, 2); rt3090_rf_write(sc, 2, rf | RT3593_RESCAL); /* set reference current control to 0.33 mA */ rf = rt3090_rf_read(sc, 22); rf &= ~RT3593_CP_IC_MASK; rf |= 1 << RT3593_CP_IC_SHIFT; rt3090_rf_write(sc, 22, rf); /* enable RX CTB */ rf = rt3090_rf_read(sc, 46); rt3090_rf_write(sc, 46, rf | RT3593_RX_CTB); rf = rt3090_rf_read(sc, 20); rf &= ~(RT3593_LDO_RF_VC_MASK | RT3593_LDO_PLL_VC_MASK); rt3090_rf_write(sc, 20, rf); } else { /* enable RF block */ rf = rt3090_rf_read(sc, 1); rt3090_rf_write(sc, 1, rf | RT3070_RF_BLOCK); /* enable VCO bias current control */ rf = rt3090_rf_read(sc, 7); rt3090_rf_write(sc, 7, rf | 0x30); rf = rt3090_rf_read(sc, 9); rt3090_rf_write(sc, 9, rf | 0x0e); /* enable RX CTB */ rf = rt3090_rf_read(sc, 21); rt3090_rf_write(sc, 21, rf | RT3070_RX_CTB); /* fix Tx to Rx IQ glitch by raising RF voltage */ rf = rt3090_rf_read(sc, 27); rf &= ~0x77; if (sc->mac_rev < 0x0211) rf |= 0x03; rt3090_rf_write(sc, 27, rf); } if (sc->patch_dac && sc->mac_rev < 0x0211) { tmp = RAL_READ(sc, RT3070_LDO_CFG0); tmp = (tmp & ~0x1f000000) | 0x0d000000; RAL_WRITE(sc, RT3070_LDO_CFG0, tmp); } } static void rt5390_rf_wakeup(struct rt2860_softc *sc) { uint32_t tmp; uint8_t rf; rf = rt3090_rf_read(sc, 1); rf |= RT3070_RF_BLOCK | RT3070_PLL_PD | RT3070_RX0_PD | RT3070_TX0_PD; if (sc->mac_ver == 0x5392) rf |= RT3070_RX1_PD | RT3070_TX1_PD; rt3090_rf_write(sc, 1, rf); rf = rt3090_rf_read(sc, 6); rf |= RT3593_VCO_IC | RT3593_VCOCAL; if (sc->mac_ver == 0x5390) rf &= ~RT3593_VCO_IC; rt3090_rf_write(sc, 6, rf); rt3090_rf_write(sc, 2, rt3090_rf_read(sc, 2) | RT3593_RESCAL); rf = rt3090_rf_read(sc, 22); rf = (rf & ~0xe0) | 0x20; rt3090_rf_write(sc, 22, rf); rt3090_rf_write(sc, 42, rt3090_rf_read(sc, 42) | RT5390_RX_CTB); rt3090_rf_write(sc, 20, rt3090_rf_read(sc, 20) & ~0x77); rt3090_rf_write(sc, 3, rt3090_rf_read(sc, 3) | RT3593_VCOCAL); if (sc->patch_dac && sc->mac_rev < 0x0211) { tmp = RAL_READ(sc, RT3070_LDO_CFG0); tmp = (tmp & ~0x1f000000) | 0x0d000000; RAL_WRITE(sc, RT3070_LDO_CFG0, tmp); } } static int rt3090_filter_calib(struct rt2860_softc *sc, uint8_t init, uint8_t target, uint8_t *val) { uint8_t rf22, rf24; uint8_t bbp55_pb, bbp55_sb, delta; int ntries; /* program filter */ rf24 = rt3090_rf_read(sc, 24); rf24 = (rf24 & 0xc0) | init; /* initial filter value */ rt3090_rf_write(sc, 24, rf24); /* enable baseband loopback mode */ rf22 = rt3090_rf_read(sc, 22); rt3090_rf_write(sc, 22, rf22 | RT3070_BB_LOOPBACK); /* set power and frequency of passband test tone */ rt2860_mcu_bbp_write(sc, 24, 0x00); for (ntries = 0; ntries < 100; ntries++) { /* transmit test tone */ rt2860_mcu_bbp_write(sc, 25, 0x90); DELAY(1000); /* read received power */ bbp55_pb = rt2860_mcu_bbp_read(sc, 55); if (bbp55_pb != 0) break; } if (ntries == 100) return (ETIMEDOUT); /* set power and frequency of stopband test tone */ rt2860_mcu_bbp_write(sc, 24, 0x06); for (ntries = 0; ntries < 100; ntries++) { /* transmit test tone */ rt2860_mcu_bbp_write(sc, 25, 0x90); DELAY(1000); /* read received power */ bbp55_sb = rt2860_mcu_bbp_read(sc, 55); delta = bbp55_pb - bbp55_sb; if (delta > target) break; /* reprogram filter */ rf24++; rt3090_rf_write(sc, 24, rf24); } if (ntries < 100) { if (rf24 != init) rf24--; /* backtrack */ *val = rf24; rt3090_rf_write(sc, 24, rf24); } /* restore initial state */ rt2860_mcu_bbp_write(sc, 24, 0x00); /* disable baseband loopback mode */ rf22 = rt3090_rf_read(sc, 22); rt3090_rf_write(sc, 22, rf22 & ~RT3070_BB_LOOPBACK); return (0); } static void rt3090_rf_setup(struct rt2860_softc *sc) { uint8_t bbp; int i; if (sc->mac_rev >= 0x0211) { /* enable DC filter */ rt2860_mcu_bbp_write(sc, 103, 0xc0); /* improve power consumption */ bbp = rt2860_mcu_bbp_read(sc, 31); rt2860_mcu_bbp_write(sc, 31, bbp & ~0x03); } RAL_WRITE(sc, RT2860_TX_SW_CFG1, 0); if (sc->mac_rev < 0x0211) { RAL_WRITE(sc, RT2860_TX_SW_CFG2, sc->patch_dac ? 0x2c : 0x0f); } else RAL_WRITE(sc, RT2860_TX_SW_CFG2, 0); /* initialize RF registers from ROM */ if (sc->mac_ver < 0x5390) { for (i = 0; i < 10; i++) { if (sc->rf[i].reg == 0 || sc->rf[i].reg == 0xff) continue; rt3090_rf_write(sc, sc->rf[i].reg, sc->rf[i].val); } } } static void rt2860_set_leds(struct rt2860_softc *sc, uint16_t which) { rt2860_mcu_cmd(sc, RT2860_MCU_CMD_LEDS, which | (sc->leds & 0x7f), 0); } /* * Hardware has a general-purpose programmable timer interrupt that can * periodically raise MAC_INT_4. */ static void rt2860_set_gp_timer(struct rt2860_softc *sc, int ms) { uint32_t tmp; /* disable GP timer before reprogramming it */ tmp = RAL_READ(sc, RT2860_INT_TIMER_EN); RAL_WRITE(sc, RT2860_INT_TIMER_EN, tmp & ~RT2860_GP_TIMER_EN); if (ms == 0) return; tmp = RAL_READ(sc, RT2860_INT_TIMER_CFG); ms *= 16; /* Unit: 64us */ tmp = (tmp & 0xffff) | ms << RT2860_GP_TIMER_SHIFT; RAL_WRITE(sc, RT2860_INT_TIMER_CFG, tmp); /* enable GP timer */ tmp = RAL_READ(sc, RT2860_INT_TIMER_EN); RAL_WRITE(sc, RT2860_INT_TIMER_EN, tmp | RT2860_GP_TIMER_EN); } static void rt2860_set_bssid(struct rt2860_softc *sc, const uint8_t *bssid) { RAL_WRITE(sc, RT2860_MAC_BSSID_DW0, bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24); RAL_WRITE(sc, RT2860_MAC_BSSID_DW1, bssid[4] | bssid[5] << 8); } static void rt2860_set_macaddr(struct rt2860_softc *sc, const uint8_t *addr) { RAL_WRITE(sc, RT2860_MAC_ADDR_DW0, addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24); RAL_WRITE(sc, RT2860_MAC_ADDR_DW1, addr[4] | addr[5] << 8 | 0xff << 16); } static void rt2860_updateslot(struct ieee80211com *ic) { struct rt2860_softc *sc = ic->ic_softc; uint32_t tmp; tmp = RAL_READ(sc, RT2860_BKOFF_SLOT_CFG); tmp &= ~0xff; tmp |= IEEE80211_GET_SLOTTIME(ic); RAL_WRITE(sc, RT2860_BKOFF_SLOT_CFG, tmp); } static void rt2860_updateprot(struct rt2860_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; uint32_t tmp; tmp = RT2860_RTSTH_EN | RT2860_PROT_NAV_SHORT | RT2860_TXOP_ALLOW_ALL; /* setup protection frame rate (MCS code) */ tmp |= IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ? rt2860_rates[RT2860_RIDX_OFDM6].mcs : rt2860_rates[RT2860_RIDX_CCK11].mcs; /* CCK frames don't require protection */ RAL_WRITE(sc, RT2860_CCK_PROT_CFG, tmp); if (ic->ic_flags & IEEE80211_F_USEPROT) { if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) tmp |= RT2860_PROT_CTRL_RTS_CTS; else if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) tmp |= RT2860_PROT_CTRL_CTS; } RAL_WRITE(sc, RT2860_OFDM_PROT_CFG, tmp); } static void rt2860_update_promisc(struct ieee80211com *ic) { struct rt2860_softc *sc = ic->ic_softc; uint32_t tmp; tmp = RAL_READ(sc, RT2860_RX_FILTR_CFG); tmp &= ~RT2860_DROP_NOT_MYBSS; if (ic->ic_promisc == 0) tmp |= RT2860_DROP_NOT_MYBSS; RAL_WRITE(sc, RT2860_RX_FILTR_CFG, tmp); } static int rt2860_updateedca(struct ieee80211com *ic) { struct rt2860_softc *sc = ic->ic_softc; const struct wmeParams *wmep; int aci; wmep = ic->ic_wme.wme_chanParams.cap_wmeParams; /* update MAC TX configuration registers */ for (aci = 0; aci < WME_NUM_AC; aci++) { RAL_WRITE(sc, RT2860_EDCA_AC_CFG(aci), wmep[aci].wmep_logcwmax << 16 | wmep[aci].wmep_logcwmin << 12 | wmep[aci].wmep_aifsn << 8 | wmep[aci].wmep_txopLimit); } /* update SCH/DMA registers too */ RAL_WRITE(sc, RT2860_WMM_AIFSN_CFG, wmep[WME_AC_VO].wmep_aifsn << 12 | wmep[WME_AC_VI].wmep_aifsn << 8 | wmep[WME_AC_BK].wmep_aifsn << 4 | wmep[WME_AC_BE].wmep_aifsn); RAL_WRITE(sc, RT2860_WMM_CWMIN_CFG, wmep[WME_AC_VO].wmep_logcwmin << 12 | wmep[WME_AC_VI].wmep_logcwmin << 8 | wmep[WME_AC_BK].wmep_logcwmin << 4 | wmep[WME_AC_BE].wmep_logcwmin); RAL_WRITE(sc, RT2860_WMM_CWMAX_CFG, wmep[WME_AC_VO].wmep_logcwmax << 12 | wmep[WME_AC_VI].wmep_logcwmax << 8 | wmep[WME_AC_BK].wmep_logcwmax << 4 | wmep[WME_AC_BE].wmep_logcwmax); RAL_WRITE(sc, RT2860_WMM_TXOP0_CFG, wmep[WME_AC_BK].wmep_txopLimit << 16 | wmep[WME_AC_BE].wmep_txopLimit); RAL_WRITE(sc, RT2860_WMM_TXOP1_CFG, wmep[WME_AC_VO].wmep_txopLimit << 16 | wmep[WME_AC_VI].wmep_txopLimit); return 0; } #ifdef HW_CRYPTO static int rt2860_set_key(struct ieee80211com *ic, struct ieee80211_node *ni, struct ieee80211_key *k) { struct rt2860_softc *sc = ic->ic_softc; bus_size_t base; uint32_t attr; uint8_t mode, wcid, iv[8]; /* defer setting of WEP keys until interface is brought up */ if ((ic->ic_if.if_flags & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING)) return 0; /* map net80211 cipher to RT2860 security mode */ switch (k->k_cipher) { case IEEE80211_CIPHER_WEP40: mode = RT2860_MODE_WEP40; break; case IEEE80211_CIPHER_WEP104: mode = RT2860_MODE_WEP104; break; case IEEE80211_CIPHER_TKIP: mode = RT2860_MODE_TKIP; break; case IEEE80211_CIPHER_CCMP: mode = RT2860_MODE_AES_CCMP; break; default: return EINVAL; } if (k->k_flags & IEEE80211_KEY_GROUP) { wcid = 0; /* NB: update WCID0 for group keys */ base = RT2860_SKEY(0, k->k_id); } else { wcid = ((struct rt2860_node *)ni)->wcid; base = RT2860_PKEY(wcid); } if (k->k_cipher == IEEE80211_CIPHER_TKIP) { RAL_WRITE_REGION_1(sc, base, k->k_key, 16); #ifndef IEEE80211_STA_ONLY if (ic->ic_opmode == IEEE80211_M_HOSTAP) { RAL_WRITE_REGION_1(sc, base + 16, &k->k_key[16], 8); RAL_WRITE_REGION_1(sc, base + 24, &k->k_key[24], 8); } else #endif { RAL_WRITE_REGION_1(sc, base + 16, &k->k_key[24], 8); RAL_WRITE_REGION_1(sc, base + 24, &k->k_key[16], 8); } } else RAL_WRITE_REGION_1(sc, base, k->k_key, k->k_len); if (!(k->k_flags & IEEE80211_KEY_GROUP) || (k->k_flags & IEEE80211_KEY_TX)) { /* set initial packet number in IV+EIV */ if (k->k_cipher == IEEE80211_CIPHER_WEP40 || k->k_cipher == IEEE80211_CIPHER_WEP104) { uint32_t val = arc4random(); /* skip weak IVs from Fluhrer/Mantin/Shamir */ if (val >= 0x03ff00 && (val & 0xf8ff00) == 0x00ff00) val += 0x000100; iv[0] = val; iv[1] = val >> 8; iv[2] = val >> 16; iv[3] = k->k_id << 6; iv[4] = iv[5] = iv[6] = iv[7] = 0; } else { if (k->k_cipher == IEEE80211_CIPHER_TKIP) { iv[0] = k->k_tsc >> 8; iv[1] = (iv[0] | 0x20) & 0x7f; iv[2] = k->k_tsc; } else /* CCMP */ { iv[0] = k->k_tsc; iv[1] = k->k_tsc >> 8; iv[2] = 0; } iv[3] = k->k_id << 6 | IEEE80211_WEP_EXTIV; iv[4] = k->k_tsc >> 16; iv[5] = k->k_tsc >> 24; iv[6] = k->k_tsc >> 32; iv[7] = k->k_tsc >> 40; } RAL_WRITE_REGION_1(sc, RT2860_IVEIV(wcid), iv, 8); } if (k->k_flags & IEEE80211_KEY_GROUP) { /* install group key */ attr = RAL_READ(sc, RT2860_SKEY_MODE_0_7); attr &= ~(0xf << (k->k_id * 4)); attr |= mode << (k->k_id * 4); RAL_WRITE(sc, RT2860_SKEY_MODE_0_7, attr); } else { /* install pairwise key */ attr = RAL_READ(sc, RT2860_WCID_ATTR(wcid)); attr = (attr & ~0xf) | (mode << 1) | RT2860_RX_PKEY_EN; RAL_WRITE(sc, RT2860_WCID_ATTR(wcid), attr); } return 0; } static void rt2860_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni, struct ieee80211_key *k) { struct rt2860_softc *sc = ic->ic_softc; uint32_t attr; uint8_t wcid; if (k->k_flags & IEEE80211_KEY_GROUP) { /* remove group key */ attr = RAL_READ(sc, RT2860_SKEY_MODE_0_7); attr &= ~(0xf << (k->k_id * 4)); RAL_WRITE(sc, RT2860_SKEY_MODE_0_7, attr); } else { /* remove pairwise key */ wcid = ((struct rt2860_node *)ni)->wcid; attr = RAL_READ(sc, RT2860_WCID_ATTR(wcid)); attr &= ~0xf; RAL_WRITE(sc, RT2860_WCID_ATTR(wcid), attr); } } #endif static int8_t rt2860_rssi2dbm(struct rt2860_softc *sc, uint8_t rssi, uint8_t rxchain) { struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_channel *c = ic->ic_curchan; int delta; if (IEEE80211_IS_CHAN_5GHZ(c)) { u_int chan = ieee80211_chan2ieee(ic, c); delta = sc->rssi_5ghz[rxchain]; /* determine channel group */ if (chan <= 64) delta -= sc->lna[1]; else if (chan <= 128) delta -= sc->lna[2]; else delta -= sc->lna[3]; } else delta = sc->rssi_2ghz[rxchain] - sc->lna[0]; return -12 - delta - rssi; } /* * Add `delta' (signed) to each 4-bit sub-word of a 32-bit word. * Used to adjust per-rate Tx power registers. */ static __inline uint32_t b4inc(uint32_t b32, int8_t delta) { int8_t i, b4; for (i = 0; i < 8; i++) { b4 = b32 & 0xf; b4 += delta; if (b4 < 0) b4 = 0; else if (b4 > 0xf) b4 = 0xf; b32 = b32 >> 4 | b4 << 28; } return b32; } static const char * -rt2860_get_rf(uint8_t rev) +rt2860_get_rf(uint16_t rev) { switch (rev) { case RT2860_RF_2820: return "RT2820"; case RT2860_RF_2850: return "RT2850"; case RT2860_RF_2720: return "RT2720"; case RT2860_RF_2750: return "RT2750"; case RT3070_RF_3020: return "RT3020"; case RT3070_RF_2020: return "RT2020"; case RT3070_RF_3021: return "RT3021"; case RT3070_RF_3022: return "RT3022"; case RT3070_RF_3052: return "RT3052"; case RT3070_RF_3320: return "RT3320"; case RT3070_RF_3053: return "RT3053"; + case RT5390_RF_5360: return "RT5360"; case RT5390_RF_5390: return "RT5390"; default: return "unknown"; } } static int rt2860_read_eeprom(struct rt2860_softc *sc, uint8_t macaddr[IEEE80211_ADDR_LEN]) { int8_t delta_2ghz, delta_5ghz; uint32_t tmp; uint16_t val; int ridx, ant, i; /* check whether the ROM is eFUSE ROM or EEPROM */ sc->sc_srom_read = rt2860_eeprom_read_2; if (sc->mac_ver >= 0x3071) { tmp = RAL_READ(sc, RT3070_EFUSE_CTRL); DPRINTF(("EFUSE_CTRL=0x%08x\n", tmp)); if (tmp & RT3070_SEL_EFUSE) sc->sc_srom_read = rt3090_efuse_read_2; } +#ifdef RAL_DEBUG /* read EEPROM version */ val = rt2860_srom_read(sc, RT2860_EEPROM_VERSION); DPRINTF(("EEPROM rev=%d, FAE=%d\n", val >> 8, val & 0xff)); +#endif /* read MAC address */ val = rt2860_srom_read(sc, RT2860_EEPROM_MAC01); macaddr[0] = val & 0xff; macaddr[1] = val >> 8; val = rt2860_srom_read(sc, RT2860_EEPROM_MAC23); macaddr[2] = val & 0xff; macaddr[3] = val >> 8; val = rt2860_srom_read(sc, RT2860_EEPROM_MAC45); macaddr[4] = val & 0xff; macaddr[5] = val >> 8; +#ifdef RAL_DEBUG /* read country code */ val = rt2860_srom_read(sc, RT2860_EEPROM_COUNTRY); DPRINTF(("EEPROM region code=0x%04x\n", val)); +#endif /* read vendor BBP settings */ for (i = 0; i < 8; i++) { val = rt2860_srom_read(sc, RT2860_EEPROM_BBP_BASE + i); sc->bbp[i].val = val & 0xff; sc->bbp[i].reg = val >> 8; DPRINTF(("BBP%d=0x%02x\n", sc->bbp[i].reg, sc->bbp[i].val)); } if (sc->mac_ver >= 0x3071) { /* read vendor RF settings */ for (i = 0; i < 10; i++) { val = rt2860_srom_read(sc, RT3071_EEPROM_RF_BASE + i); sc->rf[i].val = val & 0xff; sc->rf[i].reg = val >> 8; DPRINTF(("RF%d=0x%02x\n", sc->rf[i].reg, sc->rf[i].val)); } } /* read RF frequency offset from EEPROM */ val = rt2860_srom_read(sc, RT2860_EEPROM_FREQ_LEDS); sc->freq = ((val & 0xff) != 0xff) ? val & 0xff : 0; DPRINTF(("EEPROM freq offset %d\n", sc->freq & 0xff)); if ((val >> 8) != 0xff) { /* read LEDs operating mode */ sc->leds = val >> 8; sc->led[0] = rt2860_srom_read(sc, RT2860_EEPROM_LED1); sc->led[1] = rt2860_srom_read(sc, RT2860_EEPROM_LED2); sc->led[2] = rt2860_srom_read(sc, RT2860_EEPROM_LED3); } else { /* broken EEPROM, use default settings */ sc->leds = 0x01; sc->led[0] = 0x5555; sc->led[1] = 0x2221; sc->led[2] = 0xa9f8; } DPRINTF(("EEPROM LED mode=0x%02x, LEDs=0x%04x/0x%04x/0x%04x\n", sc->leds, sc->led[0], sc->led[1], sc->led[2])); /* read RF information */ val = rt2860_srom_read(sc, RT2860_EEPROM_ANTENNA); - if (val == 0xffff) { - DPRINTF(("invalid EEPROM antenna info, using default\n")); - if (sc->mac_ver >= 0x5390) { - /* default to RF5390 */ - sc->rf_rev = RT5390_RF_5390; - sc->ntxchains = (sc->mac_ver == 0x5392) ? 2 : 1; - sc->nrxchains = (sc->mac_ver == 0x5392) ? 2 : 1; - } else if (sc->mac_ver == 0x3593) { - /* default to RF3053 3T3R */ - sc->rf_rev = RT3070_RF_3053; - sc->ntxchains = 3; - sc->nrxchains = 3; - } else if (sc->mac_ver >= 0x3071) { - /* default to RF3020 1T1R */ - sc->rf_rev = RT3070_RF_3020; - sc->ntxchains = 1; - sc->nrxchains = 1; - } else { - /* default to RF2820 1T2R */ - sc->rf_rev = RT2860_RF_2820; - sc->ntxchains = 1; - sc->nrxchains = 2; - } - } else { + if (sc->mac_ver >= 0x5390) + sc->rf_rev = rt2860_srom_read(sc, RT2860_EEPROM_CHIPID); + else sc->rf_rev = (val >> 8) & 0xf; - if (sc->mac_ver >= 0x5390) { - sc->ntxchains = (sc->mac_ver == 0x5392) ? 2 : 1; - sc->nrxchains = (sc->mac_ver == 0x5392) ? 2 : 1; - } else { - sc->ntxchains = (val >> 4) & 0xf; - sc->nrxchains = val & 0xf; - } - } + sc->ntxchains = (val >> 4) & 0xf; + sc->nrxchains = val & 0xf; DPRINTF(("EEPROM RF rev=0x%02x chains=%dT%dR\n", sc->rf_rev, sc->ntxchains, sc->nrxchains)); /* check if RF supports automatic Tx access gain control */ val = rt2860_srom_read(sc, RT2860_EEPROM_CONFIG); DPRINTF(("EEPROM CFG 0x%04x\n", val)); /* check if driver should patch the DAC issue */ if ((val >> 8) != 0xff) sc->patch_dac = (val >> 15) & 1; if ((val & 0xff) != 0xff) { sc->ext_5ghz_lna = (val >> 3) & 1; sc->ext_2ghz_lna = (val >> 2) & 1; /* check if RF supports automatic Tx access gain control */ sc->calib_2ghz = sc->calib_5ghz = 0; /* XXX (val >> 1) & 1 */ /* check if we have a hardware radio switch */ sc->rfswitch = val & 1; } if (sc->sc_flags & RT2860_ADVANCED_PS) { /* read PCIe power save level */ val = rt2860_srom_read(sc, RT2860_EEPROM_PCIE_PSLEVEL); if ((val & 0xff) != 0xff) { sc->pslevel = val & 0x3; val = rt2860_srom_read(sc, RT2860_EEPROM_REV); if ((val & 0xff80) != 0x9280) sc->pslevel = MIN(sc->pslevel, 1); DPRINTF(("EEPROM PCIe PS Level=%d\n", sc->pslevel)); } } /* read power settings for 2GHz channels */ for (i = 0; i < 14; i += 2) { val = rt2860_srom_read(sc, RT2860_EEPROM_PWR2GHZ_BASE1 + i / 2); sc->txpow1[i + 0] = (int8_t)(val & 0xff); sc->txpow1[i + 1] = (int8_t)(val >> 8); if (sc->mac_ver != 0x5390) { val = rt2860_srom_read(sc, RT2860_EEPROM_PWR2GHZ_BASE2 + i / 2); sc->txpow2[i + 0] = (int8_t)(val & 0xff); sc->txpow2[i + 1] = (int8_t)(val >> 8); } } /* fix broken Tx power entries */ for (i = 0; i < 14; i++) { if (sc->txpow1[i] < 0 || sc->txpow1[i] > ((sc->mac_ver >= 0x5390) ? 39 : 31)) sc->txpow1[i] = 5; if (sc->mac_ver != 0x5390) { if (sc->txpow2[i] < 0 || sc->txpow2[i] > ((sc->mac_ver == 0x5392) ? 39 : 31)) sc->txpow2[i] = 5; } DPRINTF(("chan %d: power1=%d, power2=%d\n", rt2860_rf2850[i].chan, sc->txpow1[i], sc->txpow2[i])); } /* read power settings for 5GHz channels */ for (i = 0; i < 40; i += 2) { val = rt2860_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE1 + i / 2); sc->txpow1[i + 14] = (int8_t)(val & 0xff); sc->txpow1[i + 15] = (int8_t)(val >> 8); val = rt2860_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE2 + i / 2); sc->txpow2[i + 14] = (int8_t)(val & 0xff); sc->txpow2[i + 15] = (int8_t)(val >> 8); } /* fix broken Tx power entries */ for (i = 0; i < 40; i++) { if (sc->txpow1[14 + i] < -7 || sc->txpow1[14 + i] > 15) sc->txpow1[14 + i] = 5; if (sc->txpow2[14 + i] < -7 || sc->txpow2[14 + i] > 15) sc->txpow2[14 + i] = 5; DPRINTF(("chan %d: power1=%d, power2=%d\n", rt2860_rf2850[14 + i].chan, sc->txpow1[14 + i], sc->txpow2[14 + i])); } /* read Tx power compensation for each Tx rate */ val = rt2860_srom_read(sc, RT2860_EEPROM_DELTAPWR); delta_2ghz = delta_5ghz = 0; if ((val & 0xff) != 0xff && (val & 0x80)) { delta_2ghz = val & 0xf; if (!(val & 0x40)) /* negative number */ delta_2ghz = -delta_2ghz; } val >>= 8; if ((val & 0xff) != 0xff && (val & 0x80)) { delta_5ghz = val & 0xf; if (!(val & 0x40)) /* negative number */ delta_5ghz = -delta_5ghz; } DPRINTF(("power compensation=%d (2GHz), %d (5GHz)\n", delta_2ghz, delta_5ghz)); for (ridx = 0; ridx < 5; ridx++) { uint32_t reg; val = rt2860_srom_read(sc, RT2860_EEPROM_RPWR + ridx * 2); reg = val; val = rt2860_srom_read(sc, RT2860_EEPROM_RPWR + ridx * 2 + 1); reg |= (uint32_t)val << 16; sc->txpow20mhz[ridx] = reg; sc->txpow40mhz_2ghz[ridx] = b4inc(reg, delta_2ghz); sc->txpow40mhz_5ghz[ridx] = b4inc(reg, delta_5ghz); DPRINTF(("ridx %d: power 20MHz=0x%08x, 40MHz/2GHz=0x%08x, " "40MHz/5GHz=0x%08x\n", ridx, sc->txpow20mhz[ridx], sc->txpow40mhz_2ghz[ridx], sc->txpow40mhz_5ghz[ridx])); } /* read factory-calibrated samples for temperature compensation */ val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI1_2GHZ); sc->tssi_2ghz[0] = val & 0xff; /* [-4] */ sc->tssi_2ghz[1] = val >> 8; /* [-3] */ val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI2_2GHZ); sc->tssi_2ghz[2] = val & 0xff; /* [-2] */ sc->tssi_2ghz[3] = val >> 8; /* [-1] */ val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI3_2GHZ); sc->tssi_2ghz[4] = val & 0xff; /* [+0] */ sc->tssi_2ghz[5] = val >> 8; /* [+1] */ val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI4_2GHZ); sc->tssi_2ghz[6] = val & 0xff; /* [+2] */ sc->tssi_2ghz[7] = val >> 8; /* [+3] */ val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI5_2GHZ); sc->tssi_2ghz[8] = val & 0xff; /* [+4] */ sc->step_2ghz = val >> 8; DPRINTF(("TSSI 2GHz: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x " "0x%02x 0x%02x step=%d\n", sc->tssi_2ghz[0], sc->tssi_2ghz[1], sc->tssi_2ghz[2], sc->tssi_2ghz[3], sc->tssi_2ghz[4], sc->tssi_2ghz[5], sc->tssi_2ghz[6], sc->tssi_2ghz[7], sc->tssi_2ghz[8], sc->step_2ghz)); /* check that ref value is correct, otherwise disable calibration */ if (sc->tssi_2ghz[4] == 0xff) sc->calib_2ghz = 0; val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI1_5GHZ); sc->tssi_5ghz[0] = val & 0xff; /* [-4] */ sc->tssi_5ghz[1] = val >> 8; /* [-3] */ val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI2_5GHZ); sc->tssi_5ghz[2] = val & 0xff; /* [-2] */ sc->tssi_5ghz[3] = val >> 8; /* [-1] */ val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI3_5GHZ); sc->tssi_5ghz[4] = val & 0xff; /* [+0] */ sc->tssi_5ghz[5] = val >> 8; /* [+1] */ val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI4_5GHZ); sc->tssi_5ghz[6] = val & 0xff; /* [+2] */ sc->tssi_5ghz[7] = val >> 8; /* [+3] */ val = rt2860_srom_read(sc, RT2860_EEPROM_TSSI5_5GHZ); sc->tssi_5ghz[8] = val & 0xff; /* [+4] */ sc->step_5ghz = val >> 8; DPRINTF(("TSSI 5GHz: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x " "0x%02x 0x%02x step=%d\n", sc->tssi_5ghz[0], sc->tssi_5ghz[1], sc->tssi_5ghz[2], sc->tssi_5ghz[3], sc->tssi_5ghz[4], sc->tssi_5ghz[5], sc->tssi_5ghz[6], sc->tssi_5ghz[7], sc->tssi_5ghz[8], sc->step_5ghz)); /* check that ref value is correct, otherwise disable calibration */ if (sc->tssi_5ghz[4] == 0xff) sc->calib_5ghz = 0; /* read RSSI offsets and LNA gains from EEPROM */ val = rt2860_srom_read(sc, RT2860_EEPROM_RSSI1_2GHZ); sc->rssi_2ghz[0] = val & 0xff; /* Ant A */ sc->rssi_2ghz[1] = val >> 8; /* Ant B */ val = rt2860_srom_read(sc, RT2860_EEPROM_RSSI2_2GHZ); if (sc->mac_ver >= 0x3071) { /* * On RT3090 chips (limited to 2 Rx chains), this ROM * field contains the Tx mixer gain for the 2GHz band. */ if ((val & 0xff) != 0xff) sc->txmixgain_2ghz = val & 0x7; DPRINTF(("tx mixer gain=%u (2GHz)\n", sc->txmixgain_2ghz)); } else sc->rssi_2ghz[2] = val & 0xff; /* Ant C */ sc->lna[2] = val >> 8; /* channel group 2 */ val = rt2860_srom_read(sc, RT2860_EEPROM_RSSI1_5GHZ); sc->rssi_5ghz[0] = val & 0xff; /* Ant A */ sc->rssi_5ghz[1] = val >> 8; /* Ant B */ val = rt2860_srom_read(sc, RT2860_EEPROM_RSSI2_5GHZ); sc->rssi_5ghz[2] = val & 0xff; /* Ant C */ sc->lna[3] = val >> 8; /* channel group 3 */ val = rt2860_srom_read(sc, RT2860_EEPROM_LNA); if (sc->mac_ver >= 0x3071) sc->lna[0] = RT3090_DEF_LNA; else /* channel group 0 */ sc->lna[0] = val & 0xff; sc->lna[1] = val >> 8; /* channel group 1 */ /* fix broken 5GHz LNA entries */ if (sc->lna[2] == 0 || sc->lna[2] == 0xff) { DPRINTF(("invalid LNA for channel group %d\n", 2)); sc->lna[2] = sc->lna[1]; } if (sc->lna[3] == 0 || sc->lna[3] == 0xff) { DPRINTF(("invalid LNA for channel group %d\n", 3)); sc->lna[3] = sc->lna[1]; } /* fix broken RSSI offset entries */ for (ant = 0; ant < 3; ant++) { if (sc->rssi_2ghz[ant] < -10 || sc->rssi_2ghz[ant] > 10) { DPRINTF(("invalid RSSI%d offset: %d (2GHz)\n", ant + 1, sc->rssi_2ghz[ant])); sc->rssi_2ghz[ant] = 0; } if (sc->rssi_5ghz[ant] < -10 || sc->rssi_5ghz[ant] > 10) { DPRINTF(("invalid RSSI%d offset: %d (5GHz)\n", ant + 1, sc->rssi_5ghz[ant])); sc->rssi_5ghz[ant] = 0; } } return 0; } static int rt2860_bbp_init(struct rt2860_softc *sc) { int i, ntries; /* wait for BBP to wake up */ for (ntries = 0; ntries < 20; ntries++) { uint8_t bbp0 = rt2860_mcu_bbp_read(sc, 0); if (bbp0 != 0 && bbp0 != 0xff) break; } if (ntries == 20) { device_printf(sc->sc_dev, "timeout waiting for BBP to wake up\n"); return (ETIMEDOUT); } /* initialize BBP registers to default values */ if (sc->mac_ver >= 0x5390) rt5390_bbp_init(sc); else { for (i = 0; i < nitems(rt2860_def_bbp); i++) { rt2860_mcu_bbp_write(sc, rt2860_def_bbp[i].reg, rt2860_def_bbp[i].val); } } /* fix BBP84 for RT2860E */ if (sc->mac_ver == 0x2860 && sc->mac_rev != 0x0101) rt2860_mcu_bbp_write(sc, 84, 0x19); if (sc->mac_ver >= 0x3071) { rt2860_mcu_bbp_write(sc, 79, 0x13); rt2860_mcu_bbp_write(sc, 80, 0x05); rt2860_mcu_bbp_write(sc, 81, 0x33); } else if (sc->mac_ver == 0x2860 && sc->mac_rev == 0x0100) { rt2860_mcu_bbp_write(sc, 69, 0x16); rt2860_mcu_bbp_write(sc, 73, 0x12); } return 0; } static void rt5390_bbp_init(struct rt2860_softc *sc) { uint8_t bbp; int i; /* Apply maximum likelihood detection for 2 stream case. */ if (sc->nrxchains > 1) { bbp = rt2860_mcu_bbp_read(sc, 105); rt2860_mcu_bbp_write(sc, 105, bbp | RT5390_MLD); } /* Avoid data lost and CRC error. */ bbp = rt2860_mcu_bbp_read(sc, 4); rt2860_mcu_bbp_write(sc, 4, bbp | RT5390_MAC_IF_CTRL); for (i = 0; i < nitems(rt5390_def_bbp); i++) { rt2860_mcu_bbp_write(sc, rt5390_def_bbp[i].reg, rt5390_def_bbp[i].val); } if (sc->mac_ver == 0x5392) { rt2860_mcu_bbp_write(sc, 84, 0x9a); rt2860_mcu_bbp_write(sc, 95, 0x9a); rt2860_mcu_bbp_write(sc, 98, 0x12); rt2860_mcu_bbp_write(sc, 106, 0x05); rt2860_mcu_bbp_write(sc, 134, 0xd0); rt2860_mcu_bbp_write(sc, 135, 0xf6); } bbp = rt2860_mcu_bbp_read(sc, 152); rt2860_mcu_bbp_write(sc, 152, bbp | 0x80); /* Disable hardware antenna diversity. */ if (sc->mac_ver == 0x5390) rt2860_mcu_bbp_write(sc, 154, 0); } static int rt2860_txrx_enable(struct rt2860_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; uint32_t tmp; int ntries; /* enable Tx/Rx DMA engine */ RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, RT2860_MAC_TX_EN); RAL_BARRIER_READ_WRITE(sc); for (ntries = 0; ntries < 200; ntries++) { tmp = RAL_READ(sc, RT2860_WPDMA_GLO_CFG); if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0) break; DELAY(1000); } if (ntries == 200) { device_printf(sc->sc_dev, "timeout waiting for DMA engine\n"); return ETIMEDOUT; } DELAY(50); tmp |= RT2860_RX_DMA_EN | RT2860_TX_DMA_EN | RT2860_WPDMA_BT_SIZE64 << RT2860_WPDMA_BT_SIZE_SHIFT; RAL_WRITE(sc, RT2860_WPDMA_GLO_CFG, tmp); /* set Rx filter */ tmp = RT2860_DROP_CRC_ERR | RT2860_DROP_PHY_ERR; if (ic->ic_opmode != IEEE80211_M_MONITOR) { tmp |= RT2860_DROP_UC_NOME | RT2860_DROP_DUPL | RT2860_DROP_CTS | RT2860_DROP_BA | RT2860_DROP_ACK | RT2860_DROP_VER_ERR | RT2860_DROP_CTRL_RSV | RT2860_DROP_CFACK | RT2860_DROP_CFEND; if (ic->ic_opmode == IEEE80211_M_STA) tmp |= RT2860_DROP_RTS | RT2860_DROP_PSPOLL; } RAL_WRITE(sc, RT2860_RX_FILTR_CFG, tmp); RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, RT2860_MAC_RX_EN | RT2860_MAC_TX_EN); return 0; } static void rt2860_init(void *arg) { struct rt2860_softc *sc = arg; struct ieee80211com *ic = &sc->sc_ic; RAL_LOCK(sc); rt2860_init_locked(sc); RAL_UNLOCK(sc); if (sc->sc_flags & RT2860_RUNNING) ieee80211_start_all(ic); } static void rt2860_init_locked(struct rt2860_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); uint32_t tmp; uint8_t bbp1, bbp3; int i, qid, ridx, ntries, error; RAL_LOCK_ASSERT(sc); if (sc->rfswitch) { /* hardware has a radio switch on GPIO pin 2 */ if (!(RAL_READ(sc, RT2860_GPIO_CTRL) & (1 << 2))) { device_printf(sc->sc_dev, "radio is disabled by hardware switch\n"); #ifdef notyet rt2860_stop_locked(sc); return; #endif } } RAL_WRITE(sc, RT2860_PWR_PIN_CFG, RT2860_IO_RA_PE); /* disable DMA */ tmp = RAL_READ(sc, RT2860_WPDMA_GLO_CFG); tmp &= 0xff0; RAL_WRITE(sc, RT2860_WPDMA_GLO_CFG, tmp); /* PBF hardware reset */ RAL_WRITE(sc, RT2860_SYS_CTRL, 0xe1f); RAL_BARRIER_WRITE(sc); RAL_WRITE(sc, RT2860_SYS_CTRL, 0xe00); if ((error = rt2860_load_microcode(sc)) != 0) { device_printf(sc->sc_dev, "could not load 8051 microcode\n"); rt2860_stop_locked(sc); return; } rt2860_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr); /* init Tx power for all Tx rates (from EEPROM) */ for (ridx = 0; ridx < 5; ridx++) { if (sc->txpow20mhz[ridx] == 0xffffffff) continue; RAL_WRITE(sc, RT2860_TX_PWR_CFG(ridx), sc->txpow20mhz[ridx]); } for (ntries = 0; ntries < 100; ntries++) { tmp = RAL_READ(sc, RT2860_WPDMA_GLO_CFG); if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0) break; DELAY(1000); } if (ntries == 100) { device_printf(sc->sc_dev, "timeout waiting for DMA engine\n"); rt2860_stop_locked(sc); return; } tmp &= 0xff0; RAL_WRITE(sc, RT2860_WPDMA_GLO_CFG, tmp); /* reset Rx ring and all 6 Tx rings */ RAL_WRITE(sc, RT2860_WPDMA_RST_IDX, 0x1003f); /* PBF hardware reset */ RAL_WRITE(sc, RT2860_SYS_CTRL, 0xe1f); RAL_BARRIER_WRITE(sc); RAL_WRITE(sc, RT2860_SYS_CTRL, 0xe00); RAL_WRITE(sc, RT2860_PWR_PIN_CFG, RT2860_IO_RA_PE | RT2860_IO_RF_PE); RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, RT2860_BBP_HRST | RT2860_MAC_SRST); RAL_BARRIER_WRITE(sc); RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, 0); for (i = 0; i < nitems(rt2860_def_mac); i++) RAL_WRITE(sc, rt2860_def_mac[i].reg, rt2860_def_mac[i].val); if (sc->mac_ver >= 0x5390) RAL_WRITE(sc, RT2860_TX_SW_CFG0, 0x00000404); else if (sc->mac_ver >= 0x3071) { /* set delay of PA_PE assertion to 1us (unit of 0.25us) */ RAL_WRITE(sc, RT2860_TX_SW_CFG0, 4 << RT2860_DLY_PAPE_EN_SHIFT); } if (!(RAL_READ(sc, RT2860_PCI_CFG) & RT2860_PCI_CFG_PCI)) { sc->sc_flags |= RT2860_PCIE; /* PCIe has different clock cycle count than PCI */ tmp = RAL_READ(sc, RT2860_US_CYC_CNT); tmp = (tmp & ~0xff) | 0x7d; RAL_WRITE(sc, RT2860_US_CYC_CNT, tmp); } /* wait while MAC is busy */ for (ntries = 0; ntries < 100; ntries++) { if (!(RAL_READ(sc, RT2860_MAC_STATUS_REG) & (RT2860_RX_STATUS_BUSY | RT2860_TX_STATUS_BUSY))) break; DELAY(1000); } if (ntries == 100) { device_printf(sc->sc_dev, "timeout waiting for MAC\n"); rt2860_stop_locked(sc); return; } /* clear Host to MCU mailbox */ RAL_WRITE(sc, RT2860_H2M_BBPAGENT, 0); RAL_WRITE(sc, RT2860_H2M_MAILBOX, 0); rt2860_mcu_cmd(sc, RT2860_MCU_CMD_RFRESET, 0, 0); DELAY(1000); if ((error = rt2860_bbp_init(sc)) != 0) { rt2860_stop_locked(sc); return; } /* clear RX WCID search table */ RAL_SET_REGION_4(sc, RT2860_WCID_ENTRY(0), 0, 512); /* clear pairwise key table */ RAL_SET_REGION_4(sc, RT2860_PKEY(0), 0, 2048); /* clear IV/EIV table */ RAL_SET_REGION_4(sc, RT2860_IVEIV(0), 0, 512); /* clear WCID attribute table */ RAL_SET_REGION_4(sc, RT2860_WCID_ATTR(0), 0, 256); /* clear shared key table */ RAL_SET_REGION_4(sc, RT2860_SKEY(0, 0), 0, 8 * 32); /* clear shared key mode */ RAL_SET_REGION_4(sc, RT2860_SKEY_MODE_0_7, 0, 4); /* init Tx rings (4 EDCAs + HCCA + Mgt) */ for (qid = 0; qid < 6; qid++) { RAL_WRITE(sc, RT2860_TX_BASE_PTR(qid), sc->txq[qid].paddr); RAL_WRITE(sc, RT2860_TX_MAX_CNT(qid), RT2860_TX_RING_COUNT); RAL_WRITE(sc, RT2860_TX_CTX_IDX(qid), 0); } /* init Rx ring */ RAL_WRITE(sc, RT2860_RX_BASE_PTR, sc->rxq.paddr); RAL_WRITE(sc, RT2860_RX_MAX_CNT, RT2860_RX_RING_COUNT); RAL_WRITE(sc, RT2860_RX_CALC_IDX, RT2860_RX_RING_COUNT - 1); /* setup maximum buffer sizes */ RAL_WRITE(sc, RT2860_MAX_LEN_CFG, 1 << 12 | (MCLBYTES - sizeof (struct rt2860_rxwi) - 2)); for (ntries = 0; ntries < 100; ntries++) { tmp = RAL_READ(sc, RT2860_WPDMA_GLO_CFG); if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0) break; DELAY(1000); } if (ntries == 100) { device_printf(sc->sc_dev, "timeout waiting for DMA engine\n"); rt2860_stop_locked(sc); return; } tmp &= 0xff0; RAL_WRITE(sc, RT2860_WPDMA_GLO_CFG, tmp); /* disable interrupts mitigation */ RAL_WRITE(sc, RT2860_DELAY_INT_CFG, 0); /* write vendor-specific BBP values (from EEPROM) */ for (i = 0; i < 8; i++) { if (sc->bbp[i].reg == 0 || sc->bbp[i].reg == 0xff) continue; rt2860_mcu_bbp_write(sc, sc->bbp[i].reg, sc->bbp[i].val); } /* select Main antenna for 1T1R devices */ if (sc->rf_rev == RT3070_RF_2020 || sc->rf_rev == RT3070_RF_3020 || sc->rf_rev == RT3070_RF_3320 || sc->mac_ver == 0x5390) rt3090_set_rx_antenna(sc, 0); /* send LEDs operating mode to microcontroller */ rt2860_mcu_cmd(sc, RT2860_MCU_CMD_LED1, sc->led[0], 0); rt2860_mcu_cmd(sc, RT2860_MCU_CMD_LED2, sc->led[1], 0); rt2860_mcu_cmd(sc, RT2860_MCU_CMD_LED3, sc->led[2], 0); if (sc->mac_ver >= 0x5390) rt5390_rf_init(sc); else if (sc->mac_ver >= 0x3071) { if ((error = rt3090_rf_init(sc)) != 0) { rt2860_stop_locked(sc); return; } } rt2860_mcu_cmd(sc, RT2860_MCU_CMD_SLEEP, 0x02ff, 1); rt2860_mcu_cmd(sc, RT2860_MCU_CMD_WAKEUP, 0, 1); if (sc->mac_ver >= 0x5390) rt5390_rf_wakeup(sc); else if (sc->mac_ver >= 0x3071) rt3090_rf_wakeup(sc); /* disable non-existing Rx chains */ bbp3 = rt2860_mcu_bbp_read(sc, 3); bbp3 &= ~(1 << 3 | 1 << 4); if (sc->nrxchains == 2) bbp3 |= 1 << 3; else if (sc->nrxchains == 3) bbp3 |= 1 << 4; rt2860_mcu_bbp_write(sc, 3, bbp3); /* disable non-existing Tx chains */ bbp1 = rt2860_mcu_bbp_read(sc, 1); if (sc->ntxchains == 1) bbp1 = (bbp1 & ~(1 << 3 | 1 << 4)); else if (sc->mac_ver == 0x3593 && sc->ntxchains == 2) bbp1 = (bbp1 & ~(1 << 4)) | 1 << 3; else if (sc->mac_ver == 0x3593 && sc->ntxchains == 3) bbp1 = (bbp1 & ~(1 << 3)) | 1 << 4; rt2860_mcu_bbp_write(sc, 1, bbp1); if (sc->mac_ver >= 0x3071) rt3090_rf_setup(sc); /* select default channel */ rt2860_switch_chan(sc, ic->ic_curchan); /* reset RF from MCU */ rt2860_mcu_cmd(sc, RT2860_MCU_CMD_RFRESET, 0, 0); /* set RTS threshold */ tmp = RAL_READ(sc, RT2860_TX_RTS_CFG); tmp &= ~0xffff00; tmp |= IEEE80211_RTS_DEFAULT << 8; RAL_WRITE(sc, RT2860_TX_RTS_CFG, tmp); /* setup initial protection mode */ rt2860_updateprot(sc); /* turn radio LED on */ rt2860_set_leds(sc, RT2860_LED_RADIO); /* enable Tx/Rx DMA engine */ if ((error = rt2860_txrx_enable(sc)) != 0) { rt2860_stop_locked(sc); return; } /* clear pending interrupts */ RAL_WRITE(sc, RT2860_INT_STATUS, 0xffffffff); /* enable interrupts */ RAL_WRITE(sc, RT2860_INT_MASK, 0x3fffc); if (sc->sc_flags & RT2860_ADVANCED_PS) rt2860_mcu_cmd(sc, RT2860_MCU_CMD_PSLEVEL, sc->pslevel, 0); sc->sc_flags |= RT2860_RUNNING; callout_reset(&sc->watchdog_ch, hz, rt2860_watchdog, sc); } static void rt2860_stop(void *arg) { struct rt2860_softc *sc = arg; RAL_LOCK(sc); rt2860_stop_locked(sc); RAL_UNLOCK(sc); } static void rt2860_stop_locked(struct rt2860_softc *sc) { uint32_t tmp; int qid; if (sc->sc_flags & RT2860_RUNNING) rt2860_set_leds(sc, 0); /* turn all LEDs off */ callout_stop(&sc->watchdog_ch); sc->sc_tx_timer = 0; sc->sc_flags &= ~RT2860_RUNNING; /* disable interrupts */ RAL_WRITE(sc, RT2860_INT_MASK, 0); /* disable GP timer */ rt2860_set_gp_timer(sc, 0); /* disable Rx */ tmp = RAL_READ(sc, RT2860_MAC_SYS_CTRL); tmp &= ~(RT2860_MAC_RX_EN | RT2860_MAC_TX_EN); RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, tmp); /* reset adapter */ RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, RT2860_BBP_HRST | RT2860_MAC_SRST); RAL_BARRIER_WRITE(sc); RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, 0); /* reset Tx and Rx rings (and reclaim TXWIs) */ sc->qfullmsk = 0; for (qid = 0; qid < 6; qid++) rt2860_reset_tx_ring(sc, &sc->txq[qid]); rt2860_reset_rx_ring(sc, &sc->rxq); } int rt2860_load_microcode(struct rt2860_softc *sc) { const struct firmware *fp; int ntries, error; RAL_LOCK_ASSERT(sc); RAL_UNLOCK(sc); fp = firmware_get("rt2860fw"); RAL_LOCK(sc); if (fp == NULL) { device_printf(sc->sc_dev, "unable to receive rt2860fw firmware image\n"); return EINVAL; } /* set "host program ram write selection" bit */ RAL_WRITE(sc, RT2860_SYS_CTRL, RT2860_HST_PM_SEL); /* write microcode image */ RAL_WRITE_REGION_1(sc, RT2860_FW_BASE, fp->data, fp->datasize); /* kick microcontroller unit */ RAL_WRITE(sc, RT2860_SYS_CTRL, 0); RAL_BARRIER_WRITE(sc); RAL_WRITE(sc, RT2860_SYS_CTRL, RT2860_MCU_RESET); RAL_WRITE(sc, RT2860_H2M_BBPAGENT, 0); RAL_WRITE(sc, RT2860_H2M_MAILBOX, 0); /* wait until microcontroller is ready */ RAL_BARRIER_READ_WRITE(sc); for (ntries = 0; ntries < 1000; ntries++) { if (RAL_READ(sc, RT2860_SYS_CTRL) & RT2860_MCU_READY) break; DELAY(1000); } if (ntries == 1000) { device_printf(sc->sc_dev, "timeout waiting for MCU to initialize\n"); error = ETIMEDOUT; } else error = 0; firmware_put(fp, FIRMWARE_UNLOAD); return error; } /* * This function is called periodically to adjust Tx power based on * temperature variation. */ #ifdef NOT_YET static void rt2860_calib(struct rt2860_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; const uint8_t *tssi; uint8_t step, bbp49; int8_t ridx, d; /* read current temperature */ bbp49 = rt2860_mcu_bbp_read(sc, 49); if (IEEE80211_IS_CHAN_2GHZ(ic->ic_bss->ni_chan)) { tssi = &sc->tssi_2ghz[4]; step = sc->step_2ghz; } else { tssi = &sc->tssi_5ghz[4]; step = sc->step_5ghz; } if (bbp49 < tssi[0]) { /* lower than reference */ /* use higher Tx power than default */ for (d = 0; d > -4 && bbp49 <= tssi[d - 1]; d--); } else if (bbp49 > tssi[0]) { /* greater than reference */ /* use lower Tx power than default */ for (d = 0; d < +4 && bbp49 >= tssi[d + 1]; d++); } else { /* use default Tx power */ d = 0; } d *= step; DPRINTF(("BBP49=0x%02x, adjusting Tx power by %d\n", bbp49, d)); /* write adjusted Tx power values for each Tx rate */ for (ridx = 0; ridx < 5; ridx++) { if (sc->txpow20mhz[ridx] == 0xffffffff) continue; RAL_WRITE(sc, RT2860_TX_PWR_CFG(ridx), b4inc(sc->txpow20mhz[ridx], d)); } } #endif static void rt3090_set_rx_antenna(struct rt2860_softc *sc, int aux) { uint32_t tmp; if (aux) { if (sc->mac_ver == 0x5390) { rt2860_mcu_bbp_write(sc, 152, rt2860_mcu_bbp_read(sc, 152) & ~0x80); } else { tmp = RAL_READ(sc, RT2860_PCI_EECTRL); RAL_WRITE(sc, RT2860_PCI_EECTRL, tmp & ~RT2860_C); tmp = RAL_READ(sc, RT2860_GPIO_CTRL); RAL_WRITE(sc, RT2860_GPIO_CTRL, (tmp & ~0x0808) | 0x08); } } else { if (sc->mac_ver == 0x5390) { rt2860_mcu_bbp_write(sc, 152, rt2860_mcu_bbp_read(sc, 152) | 0x80); } else { tmp = RAL_READ(sc, RT2860_PCI_EECTRL); RAL_WRITE(sc, RT2860_PCI_EECTRL, tmp | RT2860_C); tmp = RAL_READ(sc, RT2860_GPIO_CTRL); RAL_WRITE(sc, RT2860_GPIO_CTRL, tmp & ~0x0808); } } } static void rt2860_switch_chan(struct rt2860_softc *sc, struct ieee80211_channel *c) { struct ieee80211com *ic = &sc->sc_ic; u_int chan, group; chan = ieee80211_chan2ieee(ic, c); if (chan == 0 || chan == IEEE80211_CHAN_ANY) return; if (sc->mac_ver >= 0x5390) rt5390_set_chan(sc, chan); else if (sc->mac_ver >= 0x3071) rt3090_set_chan(sc, chan); else rt2860_set_chan(sc, chan); /* determine channel group */ if (chan <= 14) group = 0; else if (chan <= 64) group = 1; else if (chan <= 128) group = 2; else group = 3; /* XXX necessary only when group has changed! */ if (sc->mac_ver < 0x5390) rt2860_select_chan_group(sc, group); DELAY(1000); } static int rt2860_setup_beacon(struct rt2860_softc *sc, struct ieee80211vap *vap) { struct ieee80211com *ic = vap->iv_ic; struct rt2860_txwi txwi; struct mbuf *m; int ridx; if ((m = ieee80211_beacon_alloc(vap->iv_bss)) == NULL) return ENOBUFS; memset(&txwi, 0, sizeof txwi); txwi.wcid = 0xff; txwi.len = htole16(m->m_pkthdr.len); /* send beacons at the lowest available rate */ ridx = IEEE80211_IS_CHAN_5GHZ(ic->ic_bsschan) ? RT2860_RIDX_OFDM6 : RT2860_RIDX_CCK1; txwi.phy = htole16(rt2860_rates[ridx].mcs); if (rt2860_rates[ridx].phy == IEEE80211_T_OFDM) txwi.phy |= htole16(RT2860_PHY_OFDM); txwi.txop = RT2860_TX_TXOP_HT; txwi.flags = RT2860_TX_TS; txwi.xflags = RT2860_TX_NSEQ; RAL_WRITE_REGION_1(sc, RT2860_BCN_BASE(0), (uint8_t *)&txwi, sizeof txwi); RAL_WRITE_REGION_1(sc, RT2860_BCN_BASE(0) + sizeof txwi, mtod(m, uint8_t *), m->m_pkthdr.len); m_freem(m); return 0; } static void rt2860_enable_tsf_sync(struct rt2860_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); uint32_t tmp; tmp = RAL_READ(sc, RT2860_BCN_TIME_CFG); tmp &= ~0x1fffff; tmp |= vap->iv_bss->ni_intval * 16; tmp |= RT2860_TSF_TIMER_EN | RT2860_TBTT_TIMER_EN; if (vap->iv_opmode == IEEE80211_M_STA) { /* * Local TSF is always updated with remote TSF on beacon * reception. */ tmp |= 1 << RT2860_TSF_SYNC_MODE_SHIFT; } else if (vap->iv_opmode == IEEE80211_M_IBSS || vap->iv_opmode == IEEE80211_M_MBSS) { tmp |= RT2860_BCN_TX_EN; /* * Local TSF is updated with remote TSF on beacon reception * only if the remote TSF is greater than local TSF. */ tmp |= 2 << RT2860_TSF_SYNC_MODE_SHIFT; } else if (vap->iv_opmode == IEEE80211_M_HOSTAP) { tmp |= RT2860_BCN_TX_EN; /* SYNC with nobody */ tmp |= 3 << RT2860_TSF_SYNC_MODE_SHIFT; } RAL_WRITE(sc, RT2860_BCN_TIME_CFG, tmp); } Index: head/sys/dev/ral/rt2860reg.h =================================================================== --- head/sys/dev/ral/rt2860reg.h (revision 300005) +++ head/sys/dev/ral/rt2860reg.h (revision 300006) @@ -1,1355 +1,1357 @@ /*- * Copyright (c) 2007 Damien Bergamini * Copyright (c) 2012 Bernhard Schmidt * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $OpenBSD: rt2860reg.h,v 1.30 2010/05/10 18:17:10 damien Exp $ * $FreeBSD$ */ #define RT2860_NOISE_FLOOR -95 /* PCI registers */ #define RT2860_PCI_CFG 0x0000 #define RT2860_PCI_EECTRL 0x0004 #define RT2860_PCI_MCUCTRL 0x0008 #define RT2860_PCI_SYSCTRL 0x000c #define RT2860_PCIE_JTAG 0x0010 #define RT3090_AUX_CTRL 0x010c #define RT3070_OPT_14 0x0114 /* SCH/DMA registers */ #define RT2860_INT_STATUS 0x0200 #define RT2860_INT_MASK 0x0204 #define RT2860_WPDMA_GLO_CFG 0x0208 #define RT2860_WPDMA_RST_IDX 0x020c #define RT2860_DELAY_INT_CFG 0x0210 #define RT2860_WMM_AIFSN_CFG 0x0214 #define RT2860_WMM_CWMIN_CFG 0x0218 #define RT2860_WMM_CWMAX_CFG 0x021c #define RT2860_WMM_TXOP0_CFG 0x0220 #define RT2860_WMM_TXOP1_CFG 0x0224 #define RT2860_GPIO_CTRL 0x0228 #define RT2860_MCU_CMD_REG 0x022c #define RT2860_TX_BASE_PTR(qid) (0x0230 + (qid) * 16) #define RT2860_TX_MAX_CNT(qid) (0x0234 + (qid) * 16) #define RT2860_TX_CTX_IDX(qid) (0x0238 + (qid) * 16) #define RT2860_TX_DTX_IDX(qid) (0x023c + (qid) * 16) #define RT2860_RX_BASE_PTR 0x0290 #define RT2860_RX_MAX_CNT 0x0294 #define RT2860_RX_CALC_IDX 0x0298 #define RT2860_FS_DRX_IDX 0x029c #define RT2860_USB_DMA_CFG 0x02a0 /* RT2870 only */ #define RT2860_US_CYC_CNT 0x02a4 /* PBF registers */ #define RT2860_SYS_CTRL 0x0400 #define RT2860_HOST_CMD 0x0404 #define RT2860_PBF_CFG 0x0408 #define RT2860_MAX_PCNT 0x040c #define RT2860_BUF_CTRL 0x0410 #define RT2860_MCU_INT_STA 0x0414 #define RT2860_MCU_INT_ENA 0x0418 #define RT2860_TXQ_IO(qid) (0x041c + (qid) * 4) #define RT2860_RX0Q_IO 0x0424 #define RT2860_BCN_OFFSET0 0x042c #define RT2860_BCN_OFFSET1 0x0430 #define RT2860_TXRXQ_STA 0x0434 #define RT2860_TXRXQ_PCNT 0x0438 #define RT2860_PBF_DBG 0x043c #define RT2860_CAP_CTRL 0x0440 /* RT3070 registers */ #define RT3070_RF_CSR_CFG 0x0500 #define RT3070_EFUSE_CTRL 0x0580 #define RT3070_EFUSE_DATA0 0x0590 #define RT3070_EFUSE_DATA1 0x0594 #define RT3070_EFUSE_DATA2 0x0598 #define RT3070_EFUSE_DATA3 0x059c #define RT3090_OSC_CTRL 0x05a4 #define RT3070_LDO_CFG0 0x05d4 #define RT3070_GPIO_SWITCH 0x05dc /* MAC registers */ #define RT2860_ASIC_VER_ID 0x1000 #define RT2860_MAC_SYS_CTRL 0x1004 #define RT2860_MAC_ADDR_DW0 0x1008 #define RT2860_MAC_ADDR_DW1 0x100c #define RT2860_MAC_BSSID_DW0 0x1010 #define RT2860_MAC_BSSID_DW1 0x1014 #define RT2860_MAX_LEN_CFG 0x1018 #define RT2860_BBP_CSR_CFG 0x101c #define RT2860_RF_CSR_CFG0 0x1020 #define RT2860_RF_CSR_CFG1 0x1024 #define RT2860_RF_CSR_CFG2 0x1028 #define RT2860_LED_CFG 0x102c /* undocumented registers */ #define RT2860_DEBUG 0x10f4 /* MAC Timing control registers */ #define RT2860_XIFS_TIME_CFG 0x1100 #define RT2860_BKOFF_SLOT_CFG 0x1104 #define RT2860_NAV_TIME_CFG 0x1108 #define RT2860_CH_TIME_CFG 0x110c #define RT2860_PBF_LIFE_TIMER 0x1110 #define RT2860_BCN_TIME_CFG 0x1114 #define RT2860_TBTT_SYNC_CFG 0x1118 #define RT2860_TSF_TIMER_DW0 0x111c #define RT2860_TSF_TIMER_DW1 0x1120 #define RT2860_TBTT_TIMER 0x1124 #define RT2860_INT_TIMER_CFG 0x1128 #define RT2860_INT_TIMER_EN 0x112c #define RT2860_CH_IDLE_TIME 0x1130 /* MAC Power Save configuration registers */ #define RT2860_MAC_STATUS_REG 0x1200 #define RT2860_PWR_PIN_CFG 0x1204 #define RT2860_AUTO_WAKEUP_CFG 0x1208 /* MAC TX configuration registers */ #define RT2860_EDCA_AC_CFG(aci) (0x1300 + (aci) * 4) #define RT2860_EDCA_TID_AC_MAP 0x1310 #define RT2860_TX_PWR_CFG(ridx) (0x1314 + (ridx) * 4) #define RT2860_TX_PIN_CFG 0x1328 #define RT2860_TX_BAND_CFG 0x132c #define RT2860_TX_SW_CFG0 0x1330 #define RT2860_TX_SW_CFG1 0x1334 #define RT2860_TX_SW_CFG2 0x1338 #define RT2860_TXOP_THRES_CFG 0x133c #define RT2860_TXOP_CTRL_CFG 0x1340 #define RT2860_TX_RTS_CFG 0x1344 #define RT2860_TX_TIMEOUT_CFG 0x1348 #define RT2860_TX_RTY_CFG 0x134c #define RT2860_TX_LINK_CFG 0x1350 #define RT2860_HT_FBK_CFG0 0x1354 #define RT2860_HT_FBK_CFG1 0x1358 #define RT2860_LG_FBK_CFG0 0x135c #define RT2860_LG_FBK_CFG1 0x1360 #define RT2860_CCK_PROT_CFG 0x1364 #define RT2860_OFDM_PROT_CFG 0x1368 #define RT2860_MM20_PROT_CFG 0x136c #define RT2860_MM40_PROT_CFG 0x1370 #define RT2860_GF20_PROT_CFG 0x1374 #define RT2860_GF40_PROT_CFG 0x1378 #define RT2860_EXP_CTS_TIME 0x137c #define RT2860_EXP_ACK_TIME 0x1380 /* MAC RX configuration registers */ #define RT2860_RX_FILTR_CFG 0x1400 #define RT2860_AUTO_RSP_CFG 0x1404 #define RT2860_LEGACY_BASIC_RATE 0x1408 #define RT2860_HT_BASIC_RATE 0x140c #define RT2860_HT_CTRL_CFG 0x1410 #define RT2860_SIFS_COST_CFG 0x1414 #define RT2860_RX_PARSER_CFG 0x1418 /* MAC Security configuration registers */ #define RT2860_TX_SEC_CNT0 0x1500 #define RT2860_RX_SEC_CNT0 0x1504 #define RT2860_CCMP_FC_MUTE 0x1508 /* MAC HCCA/PSMP configuration registers */ #define RT2860_TXOP_HLDR_ADDR0 0x1600 #define RT2860_TXOP_HLDR_ADDR1 0x1604 #define RT2860_TXOP_HLDR_ET 0x1608 #define RT2860_QOS_CFPOLL_RA_DW0 0x160c #define RT2860_QOS_CFPOLL_A1_DW1 0x1610 #define RT2860_QOS_CFPOLL_QC 0x1614 /* MAC Statistics Counters */ #define RT2860_RX_STA_CNT0 0x1700 #define RT2860_RX_STA_CNT1 0x1704 #define RT2860_RX_STA_CNT2 0x1708 #define RT2860_TX_STA_CNT0 0x170c #define RT2860_TX_STA_CNT1 0x1710 #define RT2860_TX_STA_CNT2 0x1714 #define RT2860_TX_STAT_FIFO 0x1718 /* RX WCID search table */ #define RT2860_WCID_ENTRY(wcid) (0x1800 + (wcid) * 8) #define RT2860_FW_BASE 0x2000 #define RT2870_FW_BASE 0x3000 /* Pair-wise key table */ #define RT2860_PKEY(wcid) (0x4000 + (wcid) * 32) /* IV/EIV table */ #define RT2860_IVEIV(wcid) (0x6000 + (wcid) * 8) /* WCID attribute table */ #define RT2860_WCID_ATTR(wcid) (0x6800 + (wcid) * 4) /* Shared Key Table */ #define RT2860_SKEY(vap, kidx) (0x6c00 + (vap) * 128 + (kidx) * 32) /* Shared Key Mode */ #define RT2860_SKEY_MODE_0_7 0x7000 #define RT2860_SKEY_MODE_8_15 0x7004 #define RT2860_SKEY_MODE_16_23 0x7008 #define RT2860_SKEY_MODE_24_31 0x700c /* Shared Memory between MCU and host */ #define RT2860_H2M_MAILBOX 0x7010 #define RT2860_H2M_MAILBOX_CID 0x7014 #define RT2860_H2M_MAILBOX_STATUS 0x701c #define RT2860_H2M_BBPAGENT 0x7028 #define RT2860_BCN_BASE(vap) (0x7800 + (vap) * 512) /* possible flags for RT2860_PCI_CFG */ #define RT2860_PCI_CFG_USB (1 << 17) #define RT2860_PCI_CFG_PCI (1 << 16) /* possible flags for register RT2860_PCI_EECTRL */ #define RT2860_C (1 << 0) #define RT2860_S (1 << 1) #define RT2860_D (1 << 2) #define RT2860_SHIFT_D 2 #define RT2860_Q (1 << 3) #define RT2860_SHIFT_Q 3 /* possible flags for registers INT_STATUS/INT_MASK */ #define RT2860_TX_COHERENT (1 << 17) #define RT2860_RX_COHERENT (1 << 16) #define RT2860_MAC_INT_4 (1 << 15) #define RT2860_MAC_INT_3 (1 << 14) #define RT2860_MAC_INT_2 (1 << 13) #define RT2860_MAC_INT_1 (1 << 12) #define RT2860_MAC_INT_0 (1 << 11) #define RT2860_TX_RX_COHERENT (1 << 10) #define RT2860_MCU_CMD_INT (1 << 9) #define RT2860_TX_DONE_INT5 (1 << 8) #define RT2860_TX_DONE_INT4 (1 << 7) #define RT2860_TX_DONE_INT3 (1 << 6) #define RT2860_TX_DONE_INT2 (1 << 5) #define RT2860_TX_DONE_INT1 (1 << 4) #define RT2860_TX_DONE_INT0 (1 << 3) #define RT2860_RX_DONE_INT (1 << 2) #define RT2860_TX_DLY_INT (1 << 1) #define RT2860_RX_DLY_INT (1 << 0) /* possible flags for register WPDMA_GLO_CFG */ #define RT2860_HDR_SEG_LEN_SHIFT 8 #define RT2860_BIG_ENDIAN (1 << 7) #define RT2860_TX_WB_DDONE (1 << 6) #define RT2860_WPDMA_BT_SIZE_SHIFT 4 #define RT2860_WPDMA_BT_SIZE16 0 #define RT2860_WPDMA_BT_SIZE32 1 #define RT2860_WPDMA_BT_SIZE64 2 #define RT2860_WPDMA_BT_SIZE128 3 #define RT2860_RX_DMA_BUSY (1 << 3) #define RT2860_RX_DMA_EN (1 << 2) #define RT2860_TX_DMA_BUSY (1 << 1) #define RT2860_TX_DMA_EN (1 << 0) /* possible flags for register DELAY_INT_CFG */ #define RT2860_TXDLY_INT_EN (1U << 31) #define RT2860_TXMAX_PINT_SHIFT 24 #define RT2860_TXMAX_PTIME_SHIFT 16 #define RT2860_RXDLY_INT_EN (1 << 15) #define RT2860_RXMAX_PINT_SHIFT 8 #define RT2860_RXMAX_PTIME_SHIFT 0 /* possible flags for register GPIO_CTRL */ #define RT2860_GPIO_D_SHIFT 8 #define RT2860_GPIO_O_SHIFT 0 /* possible flags for register USB_DMA_CFG */ #define RT2860_USB_TX_BUSY (1U << 31) #define RT2860_USB_RX_BUSY (1 << 30) #define RT2860_USB_EPOUT_VLD_SHIFT 24 #define RT2860_USB_TX_EN (1 << 23) #define RT2860_USB_RX_EN (1 << 22) #define RT2860_USB_RX_AGG_EN (1 << 21) #define RT2860_USB_TXOP_HALT (1 << 20) #define RT2860_USB_TX_CLEAR (1 << 19) #define RT2860_USB_PHY_WD_EN (1 << 16) #define RT2860_USB_PHY_MAN_RST (1 << 15) #define RT2860_USB_RX_AGG_LMT(x) ((x) << 8) /* in unit of 1KB */ #define RT2860_USB_RX_AGG_TO(x) ((x) & 0xff) /* in unit of 33ns */ /* possible flags for register US_CYC_CNT */ #define RT2860_TEST_EN (1 << 24) #define RT2860_TEST_SEL_SHIFT 16 #define RT2860_BT_MODE_EN (1 << 8) #define RT2860_US_CYC_CNT_SHIFT 0 /* possible flags for register SYS_CTRL */ #define RT2860_HST_PM_SEL (1 << 16) #define RT2860_CAP_MODE (1 << 14) #define RT2860_PME_OEN (1 << 13) #define RT2860_CLKSELECT (1 << 12) #define RT2860_PBF_CLK_EN (1 << 11) #define RT2860_MAC_CLK_EN (1 << 10) #define RT2860_DMA_CLK_EN (1 << 9) #define RT2860_MCU_READY (1 << 7) #define RT2860_ASY_RESET (1 << 4) #define RT2860_PBF_RESET (1 << 3) #define RT2860_MAC_RESET (1 << 2) #define RT2860_DMA_RESET (1 << 1) #define RT2860_MCU_RESET (1 << 0) /* possible values for register HOST_CMD */ #define RT2860_MCU_CMD_SLEEP 0x30 #define RT2860_MCU_CMD_WAKEUP 0x31 #define RT2860_MCU_CMD_LEDS 0x50 #define RT2860_MCU_CMD_LED_RSSI 0x51 #define RT2860_MCU_CMD_LED1 0x52 #define RT2860_MCU_CMD_LED2 0x53 #define RT2860_MCU_CMD_LED3 0x54 #define RT2860_MCU_CMD_RFRESET 0x72 #define RT2860_MCU_CMD_ANTSEL 0x73 #define RT2860_MCU_CMD_BBP 0x80 #define RT2860_MCU_CMD_PSLEVEL 0x83 /* possible flags for register PBF_CFG */ #define RT2860_TX1Q_NUM_SHIFT 21 #define RT2860_TX2Q_NUM_SHIFT 16 #define RT2860_NULL0_MODE (1 << 15) #define RT2860_NULL1_MODE (1 << 14) #define RT2860_RX_DROP_MODE (1 << 13) #define RT2860_TX0Q_MANUAL (1 << 12) #define RT2860_TX1Q_MANUAL (1 << 11) #define RT2860_TX2Q_MANUAL (1 << 10) #define RT2860_RX0Q_MANUAL (1 << 9) #define RT2860_HCCA_EN (1 << 8) #define RT2860_TX0Q_EN (1 << 4) #define RT2860_TX1Q_EN (1 << 3) #define RT2860_TX2Q_EN (1 << 2) #define RT2860_RX0Q_EN (1 << 1) /* possible flags for register BUF_CTRL */ #define RT2860_WRITE_TXQ(qid) (1 << (11 - (qid))) #define RT2860_NULL0_KICK (1 << 7) #define RT2860_NULL1_KICK (1 << 6) #define RT2860_BUF_RESET (1 << 5) #define RT2860_READ_TXQ(qid) (1 << (3 - (qid)) #define RT2860_READ_RX0Q (1 << 0) /* possible flags for registers MCU_INT_STA/MCU_INT_ENA */ #define RT2860_MCU_MAC_INT_8 (1 << 24) #define RT2860_MCU_MAC_INT_7 (1 << 23) #define RT2860_MCU_MAC_INT_6 (1 << 22) #define RT2860_MCU_MAC_INT_4 (1 << 20) #define RT2860_MCU_MAC_INT_3 (1 << 19) #define RT2860_MCU_MAC_INT_2 (1 << 18) #define RT2860_MCU_MAC_INT_1 (1 << 17) #define RT2860_MCU_MAC_INT_0 (1 << 16) #define RT2860_DTX0_INT (1 << 11) #define RT2860_DTX1_INT (1 << 10) #define RT2860_DTX2_INT (1 << 9) #define RT2860_DRX0_INT (1 << 8) #define RT2860_HCMD_INT (1 << 7) #define RT2860_N0TX_INT (1 << 6) #define RT2860_N1TX_INT (1 << 5) #define RT2860_BCNTX_INT (1 << 4) #define RT2860_MTX0_INT (1 << 3) #define RT2860_MTX1_INT (1 << 2) #define RT2860_MTX2_INT (1 << 1) #define RT2860_MRX0_INT (1 << 0) /* possible flags for register TXRXQ_PCNT */ #define RT2860_RX0Q_PCNT_MASK 0xff000000 #define RT2860_TX2Q_PCNT_MASK 0x00ff0000 #define RT2860_TX1Q_PCNT_MASK 0x0000ff00 #define RT2860_TX0Q_PCNT_MASK 0x000000ff /* possible flags for register CAP_CTRL */ #define RT2860_CAP_ADC_FEQ (1U << 31) #define RT2860_CAP_START (1 << 30) #define RT2860_MAN_TRIG (1 << 29) #define RT2860_TRIG_OFFSET_SHIFT 16 #define RT2860_START_ADDR_SHIFT 0 /* possible flags for register RF_CSR_CFG */ #define RT3070_RF_KICK (1 << 17) #define RT3070_RF_WRITE (1 << 16) /* possible flags for register EFUSE_CTRL */ #define RT3070_SEL_EFUSE (1U << 31) #define RT3070_EFSROM_KICK (1 << 30) #define RT3070_EFSROM_AIN_MASK 0x03ff0000 #define RT3070_EFSROM_AIN_SHIFT 16 #define RT3070_EFSROM_MODE_MASK 0x000000c0 #define RT3070_EFUSE_AOUT_MASK 0x0000003f /* possible flags for register MAC_SYS_CTRL */ #define RT2860_RX_TS_EN (1 << 7) #define RT2860_WLAN_HALT_EN (1 << 6) #define RT2860_PBF_LOOP_EN (1 << 5) #define RT2860_CONT_TX_TEST (1 << 4) #define RT2860_MAC_RX_EN (1 << 3) #define RT2860_MAC_TX_EN (1 << 2) #define RT2860_BBP_HRST (1 << 1) #define RT2860_MAC_SRST (1 << 0) /* possible flags for register MAC_BSSID_DW1 */ #define RT2860_MULTI_BCN_NUM_SHIFT 18 #define RT2860_MULTI_BSSID_MODE_SHIFT 16 /* possible flags for register MAX_LEN_CFG */ #define RT2860_MIN_MPDU_LEN_SHIFT 16 #define RT2860_MAX_PSDU_LEN_SHIFT 12 #define RT2860_MAX_PSDU_LEN8K 0 #define RT2860_MAX_PSDU_LEN16K 1 #define RT2860_MAX_PSDU_LEN32K 2 #define RT2860_MAX_PSDU_LEN64K 3 #define RT2860_MAX_MPDU_LEN_SHIFT 0 /* possible flags for registers BBP_CSR_CFG/H2M_BBPAGENT */ #define RT2860_BBP_RW_PARALLEL (1 << 19) #define RT2860_BBP_PAR_DUR_112_5 (1 << 18) #define RT2860_BBP_CSR_KICK (1 << 17) #define RT2860_BBP_CSR_READ (1 << 16) #define RT2860_BBP_ADDR_SHIFT 8 #define RT2860_BBP_DATA_SHIFT 0 /* possible flags for register RF_CSR_CFG0 */ #define RT2860_RF_REG_CTRL (1U << 31) #define RT2860_RF_LE_SEL1 (1 << 30) #define RT2860_RF_LE_STBY (1 << 29) #define RT2860_RF_REG_WIDTH_SHIFT 24 #define RT2860_RF_REG_0_SHIFT 0 /* possible flags for register RF_CSR_CFG1 */ #define RT2860_RF_DUR_5 (1 << 24) #define RT2860_RF_REG_1_SHIFT 0 /* possible flags for register LED_CFG */ #define RT2860_LED_POL (1 << 30) #define RT2860_Y_LED_MODE_SHIFT 28 #define RT2860_G_LED_MODE_SHIFT 26 #define RT2860_R_LED_MODE_SHIFT 24 #define RT2860_LED_MODE_OFF 0 #define RT2860_LED_MODE_BLINK_TX 1 #define RT2860_LED_MODE_SLOW_BLINK 2 #define RT2860_LED_MODE_ON 3 #define RT2860_SLOW_BLK_TIME_SHIFT 16 #define RT2860_LED_OFF_TIME_SHIFT 8 #define RT2860_LED_ON_TIME_SHIFT 0 /* possible flags for register XIFS_TIME_CFG */ #define RT2860_BB_RXEND_EN (1 << 29) #define RT2860_EIFS_TIME_SHIFT 20 #define RT2860_OFDM_XIFS_TIME_SHIFT 16 #define RT2860_OFDM_SIFS_TIME_SHIFT 8 #define RT2860_CCK_SIFS_TIME_SHIFT 0 /* possible flags for register BKOFF_SLOT_CFG */ #define RT2860_CC_DELAY_TIME_SHIFT 8 #define RT2860_SLOT_TIME 0 /* possible flags for register NAV_TIME_CFG */ #define RT2860_NAV_UPD (1U << 31) #define RT2860_NAV_UPD_VAL_SHIFT 16 #define RT2860_NAV_CLR_EN (1 << 15) #define RT2860_NAV_TIMER_SHIFT 0 /* possible flags for register CH_TIME_CFG */ #define RT2860_EIFS_AS_CH_BUSY (1 << 4) #define RT2860_NAV_AS_CH_BUSY (1 << 3) #define RT2860_RX_AS_CH_BUSY (1 << 2) #define RT2860_TX_AS_CH_BUSY (1 << 1) #define RT2860_CH_STA_TIMER_EN (1 << 0) /* possible values for register BCN_TIME_CFG */ #define RT2860_TSF_INS_COMP_SHIFT 24 #define RT2860_BCN_TX_EN (1 << 20) #define RT2860_TBTT_TIMER_EN (1 << 19) #define RT2860_TSF_SYNC_MODE_SHIFT 17 #define RT2860_TSF_SYNC_MODE_DIS 0 #define RT2860_TSF_SYNC_MODE_STA 1 #define RT2860_TSF_SYNC_MODE_IBSS 2 #define RT2860_TSF_SYNC_MODE_HOSTAP 3 #define RT2860_TSF_TIMER_EN (1 << 16) #define RT2860_BCN_INTVAL_SHIFT 0 /* possible flags for register TBTT_SYNC_CFG */ #define RT2860_BCN_CWMIN_SHIFT 20 #define RT2860_BCN_AIFSN_SHIFT 16 #define RT2860_BCN_EXP_WIN_SHIFT 8 #define RT2860_TBTT_ADJUST_SHIFT 0 /* possible flags for register INT_TIMER_CFG */ #define RT2860_GP_TIMER_SHIFT 16 #define RT2860_PRE_TBTT_TIMER_SHIFT 0 /* possible flags for register INT_TIMER_EN */ #define RT2860_GP_TIMER_EN (1 << 1) #define RT2860_PRE_TBTT_INT_EN (1 << 0) /* possible flags for register MAC_STATUS_REG */ #define RT2860_RX_STATUS_BUSY (1 << 1) #define RT2860_TX_STATUS_BUSY (1 << 0) /* possible flags for register PWR_PIN_CFG */ #define RT2860_IO_ADDA_PD (1 << 3) #define RT2860_IO_PLL_PD (1 << 2) #define RT2860_IO_RA_PE (1 << 1) #define RT2860_IO_RF_PE (1 << 0) /* possible flags for register AUTO_WAKEUP_CFG */ #define RT2860_AUTO_WAKEUP_EN (1 << 15) #define RT2860_SLEEP_TBTT_NUM_SHIFT 8 #define RT2860_WAKEUP_LEAD_TIME_SHIFT 0 /* possible flags for register TX_PIN_CFG */ #define RT3593_LNA_PE_G2_POL (1U << 31) #define RT3593_LNA_PE_A2_POL (1 << 30) #define RT3593_LNA_PE_G2_EN (1 << 29) #define RT3593_LNA_PE_A2_EN (1 << 28) #define RT3593_LNA_PE2_EN (RT3593_LNA_PE_A2_EN | RT3593_LNA_PE_G2_EN) #define RT3593_PA_PE_G2_POL (1 << 27) #define RT3593_PA_PE_A2_POL (1 << 26) #define RT3593_PA_PE_G2_EN (1 << 25) #define RT3593_PA_PE_A2_EN (1 << 24) #define RT2860_TRSW_POL (1 << 19) #define RT2860_TRSW_EN (1 << 18) #define RT2860_RFTR_POL (1 << 17) #define RT2860_RFTR_EN (1 << 16) #define RT2860_LNA_PE_G1_POL (1 << 15) #define RT2860_LNA_PE_A1_POL (1 << 14) #define RT2860_LNA_PE_G0_POL (1 << 13) #define RT2860_LNA_PE_A0_POL (1 << 12) #define RT2860_LNA_PE_G1_EN (1 << 11) #define RT2860_LNA_PE_A1_EN (1 << 10) #define RT2860_LNA_PE1_EN (RT2860_LNA_PE_A1_EN | RT2860_LNA_PE_G1_EN) #define RT2860_LNA_PE_G0_EN (1 << 9) #define RT2860_LNA_PE_A0_EN (1 << 8) #define RT2860_LNA_PE0_EN (RT2860_LNA_PE_A0_EN | RT2860_LNA_PE_G0_EN) #define RT2860_PA_PE_G1_POL (1 << 7) #define RT2860_PA_PE_A1_POL (1 << 6) #define RT2860_PA_PE_G0_POL (1 << 5) #define RT2860_PA_PE_A0_POL (1 << 4) #define RT2860_PA_PE_G1_EN (1 << 3) #define RT2860_PA_PE_A1_EN (1 << 2) #define RT2860_PA_PE_G0_EN (1 << 1) #define RT2860_PA_PE_A0_EN (1 << 0) /* possible flags for register TX_BAND_CFG */ #define RT2860_5G_BAND_SEL_N (1 << 2) #define RT2860_5G_BAND_SEL_P (1 << 1) #define RT2860_TX_BAND_SEL (1 << 0) /* possible flags for register TX_SW_CFG0 */ #define RT2860_DLY_RFTR_EN_SHIFT 24 #define RT2860_DLY_TRSW_EN_SHIFT 16 #define RT2860_DLY_PAPE_EN_SHIFT 8 #define RT2860_DLY_TXPE_EN_SHIFT 0 /* possible flags for register TX_SW_CFG1 */ #define RT2860_DLY_RFTR_DIS_SHIFT 16 #define RT2860_DLY_TRSW_DIS_SHIFT 8 #define RT2860_DLY_PAPE_DIS SHIFT 0 /* possible flags for register TX_SW_CFG2 */ #define RT2860_DLY_LNA_EN_SHIFT 24 #define RT2860_DLY_LNA_DIS_SHIFT 16 #define RT2860_DLY_DAC_EN_SHIFT 8 #define RT2860_DLY_DAC_DIS_SHIFT 0 /* possible flags for register TXOP_THRES_CFG */ #define RT2860_TXOP_REM_THRES_SHIFT 24 #define RT2860_CF_END_THRES_SHIFT 16 #define RT2860_RDG_IN_THRES 8 #define RT2860_RDG_OUT_THRES 0 /* possible flags for register TXOP_CTRL_CFG */ #define RT2860_EXT_CW_MIN_SHIFT 16 #define RT2860_EXT_CCA_DLY_SHIFT 8 #define RT2860_EXT_CCA_EN (1 << 7) #define RT2860_LSIG_TXOP_EN (1 << 6) #define RT2860_TXOP_TRUN_EN_MIMOPS (1 << 4) #define RT2860_TXOP_TRUN_EN_TXOP (1 << 3) #define RT2860_TXOP_TRUN_EN_RATE (1 << 2) #define RT2860_TXOP_TRUN_EN_AC (1 << 1) #define RT2860_TXOP_TRUN_EN_TIMEOUT (1 << 0) /* possible flags for register TX_RTS_CFG */ #define RT2860_RTS_FBK_EN (1 << 24) #define RT2860_RTS_THRES_SHIFT 8 #define RT2860_RTS_RTY_LIMIT_SHIFT 0 /* possible flags for register TX_TIMEOUT_CFG */ #define RT2860_TXOP_TIMEOUT_SHIFT 16 #define RT2860_RX_ACK_TIMEOUT_SHIFT 8 #define RT2860_MPDU_LIFE_TIME_SHIFT 4 /* possible flags for register TX_RTY_CFG */ #define RT2860_TX_AUTOFB_EN (1 << 30) #define RT2860_AGG_RTY_MODE_TIMER (1 << 29) #define RT2860_NAG_RTY_MODE_TIMER (1 << 28) #define RT2860_LONG_RTY_THRES_SHIFT 16 #define RT2860_LONG_RTY_LIMIT_SHIFT 8 #define RT2860_SHORT_RTY_LIMIT_SHIFT 0 /* possible flags for register TX_LINK_CFG */ #define RT2860_REMOTE_MFS_SHIFT 24 #define RT2860_REMOTE_MFB_SHIFT 16 #define RT2860_TX_CFACK_EN (1 << 12) #define RT2860_TX_RDG_EN (1 << 11) #define RT2860_TX_MRQ_EN (1 << 10) #define RT2860_REMOTE_UMFS_EN (1 << 9) #define RT2860_TX_MFB_EN (1 << 8) #define RT2860_REMOTE_MFB_LT_SHIFT 0 /* possible flags for registers *_PROT_CFG */ #define RT2860_RTSTH_EN (1 << 26) #define RT2860_TXOP_ALLOW_GF40 (1 << 25) #define RT2860_TXOP_ALLOW_GF20 (1 << 24) #define RT2860_TXOP_ALLOW_MM40 (1 << 23) #define RT2860_TXOP_ALLOW_MM20 (1 << 22) #define RT2860_TXOP_ALLOW_OFDM (1 << 21) #define RT2860_TXOP_ALLOW_CCK (1 << 20) #define RT2860_TXOP_ALLOW_ALL (0x3f << 20) #define RT2860_PROT_NAV_SHORT (1 << 18) #define RT2860_PROT_NAV_LONG (2 << 18) #define RT2860_PROT_CTRL_RTS_CTS (1 << 16) #define RT2860_PROT_CTRL_CTS (2 << 16) /* possible flags for registers EXP_{CTS,ACK}_TIME */ #define RT2860_EXP_OFDM_TIME_SHIFT 16 #define RT2860_EXP_CCK_TIME_SHIFT 0 /* possible flags for register RX_FILTR_CFG */ #define RT2860_DROP_CTRL_RSV (1 << 16) #define RT2860_DROP_BAR (1 << 15) #define RT2860_DROP_BA (1 << 14) #define RT2860_DROP_PSPOLL (1 << 13) #define RT2860_DROP_RTS (1 << 12) #define RT2860_DROP_CTS (1 << 11) #define RT2860_DROP_ACK (1 << 10) #define RT2860_DROP_CFEND (1 << 9) #define RT2860_DROP_CFACK (1 << 8) #define RT2860_DROP_DUPL (1 << 7) #define RT2860_DROP_BC (1 << 6) #define RT2860_DROP_MC (1 << 5) #define RT2860_DROP_VER_ERR (1 << 4) #define RT2860_DROP_NOT_MYBSS (1 << 3) #define RT2860_DROP_UC_NOME (1 << 2) #define RT2860_DROP_PHY_ERR (1 << 1) #define RT2860_DROP_CRC_ERR (1 << 0) /* possible flags for register AUTO_RSP_CFG */ #define RT2860_CTRL_PWR_BIT (1 << 7) #define RT2860_BAC_ACK_POLICY (1 << 6) #define RT2860_CCK_SHORT_EN (1 << 4) #define RT2860_CTS_40M_REF_EN (1 << 3) #define RT2860_CTS_40M_MODE_EN (1 << 2) #define RT2860_BAC_ACKPOLICY_EN (1 << 1) #define RT2860_AUTO_RSP_EN (1 << 0) /* possible flags for register SIFS_COST_CFG */ #define RT2860_OFDM_SIFS_COST_SHIFT 8 #define RT2860_CCK_SIFS_COST_SHIFT 0 /* possible flags for register TXOP_HLDR_ET */ #define RT2860_TXOP_ETM1_EN (1 << 25) #define RT2860_TXOP_ETM0_EN (1 << 24) #define RT2860_TXOP_ETM_THRES_SHIFT 16 #define RT2860_TXOP_ETO_EN (1 << 8) #define RT2860_TXOP_ETO_THRES_SHIFT 1 #define RT2860_PER_RX_RST_EN (1 << 0) /* possible flags for register TX_STAT_FIFO */ #define RT2860_TXQ_MCS_SHIFT 16 #define RT2860_TXQ_WCID_SHIFT 8 #define RT2860_TXQ_ACKREQ (1 << 7) #define RT2860_TXQ_AGG (1 << 6) #define RT2860_TXQ_OK (1 << 5) #define RT2860_TXQ_PID_SHIFT 1 #define RT2860_TXQ_VLD (1 << 0) /* possible flags for register WCID_ATTR */ #define RT2860_MODE_NOSEC 0 #define RT2860_MODE_WEP40 1 #define RT2860_MODE_WEP104 2 #define RT2860_MODE_TKIP 3 #define RT2860_MODE_AES_CCMP 4 #define RT2860_MODE_CKIP40 5 #define RT2860_MODE_CKIP104 6 #define RT2860_MODE_CKIP128 7 #define RT2860_RX_PKEY_EN (1 << 0) /* possible flags for register H2M_MAILBOX */ #define RT2860_H2M_BUSY (1 << 24) #define RT2860_TOKEN_NO_INTR 0xff /* possible flags for MCU command RT2860_MCU_CMD_LEDS */ #define RT2860_LED_RADIO (1 << 13) #define RT2860_LED_LINK_2GHZ (1 << 14) #define RT2860_LED_LINK_5GHZ (1 << 15) /* possible flags for RT3020 RF register 1 */ #define RT3070_RF_BLOCK (1 << 0) #define RT3070_PLL_PD (1 << 1) #define RT3070_RX0_PD (1 << 2) #define RT3070_TX0_PD (1 << 3) #define RT3070_RX1_PD (1 << 4) #define RT3070_TX1_PD (1 << 5) #define RT3070_RX2_PD (1 << 6) #define RT3070_TX2_PD (1 << 7) /* possible flags for RT3020 RF register 7 */ #define RT3070_TUNE (1 << 0) /* possible flags for RT3020 RF register 15 */ #define RT3070_TX_LO2 (1 << 3) /* possible flags for RT3020 RF register 17 */ #define RT3070_TX_LO1 (1 << 3) /* possible flags for RT3020 RF register 20 */ #define RT3070_RX_LO1 (1 << 3) /* possible flags for RT3020 RF register 21 */ #define RT3070_RX_LO2 (1 << 3) #define RT3070_RX_CTB (1 << 7) /* possible flags for RT3020 RF register 22 */ #define RT3070_BB_LOOPBACK (1 << 0) /* possible flags for RT3053 RF register 1 */ #define RT3593_VCO (1 << 0) /* possible flags for RT3053 RF register 2 */ #define RT3593_RESCAL (1 << 7) /* possible flags for RT3053 RF register 3 */ #define RT3593_VCOCAL (1 << 7) /* possible flags for RT3053 RF register 6 */ #define RT3593_VCO_IC (1 << 6) /* possible flags for RT3053 RF register 20 */ #define RT3593_LDO_PLL_VC_MASK 0x0e #define RT3593_LDO_RF_VC_MASK 0xe0 /* possible flags for RT3053 RF register 22 */ #define RT3593_CP_IC_MASK 0xe0 #define RT3593_CP_IC_SHIFT 5 /* possible flags for RT3053 RF register 46 */ #define RT3593_RX_CTB (1 << 5) #define RT3090_DEF_LNA 10 /* possible flags for RT5390 RF register 38 */ #define RT5390_RX_LO1 (1 << 5) /* possible flags for RT5390 RF register 39 */ #define RT5390_RX_LO2 (1 << 7) /* possible flags for RT5390 RF register 42 */ #define RT5390_RX_CTB (1 << 6) /* possible flags for RT5390 BBP register 4 */ #define RT5390_MAC_IF_CTRL (1 << 6) /* possible flags for RT5390 BBP register 105 */ #define RT5390_MLD (1 << 2) #define RT5390_SIG_MODULATION (1 << 3) /* RT2860 TX descriptor */ struct rt2860_txd { uint32_t sdp0; /* Segment Data Pointer 0 */ uint16_t sdl1; /* Segment Data Length 1 */ #define RT2860_TX_BURST (1 << 15) #define RT2860_TX_LS1 (1 << 14) /* SDP1 is the last segment */ uint16_t sdl0; /* Segment Data Length 0 */ #define RT2860_TX_DDONE (1 << 15) #define RT2860_TX_LS0 (1 << 14) /* SDP0 is the last segment */ uint32_t sdp1; /* Segment Data Pointer 1 */ uint8_t reserved[3]; uint8_t flags; #define RT2860_TX_QSEL_SHIFT 1 #define RT2860_TX_QSEL_MGMT (0 << 1) #define RT2860_TX_QSEL_HCCA (1 << 1) #define RT2860_TX_QSEL_EDCA (2 << 1) #define RT2860_TX_WIV (1 << 0) } __packed; /* RT2870 TX descriptor */ struct rt2870_txd { uint16_t len; uint8_t pad; uint8_t flags; } __packed; /* TX Wireless Information */ struct rt2860_txwi { uint8_t flags; #define RT2860_TX_MPDU_DSITY_SHIFT 5 #define RT2860_TX_AMPDU (1 << 4) #define RT2860_TX_TS (1 << 3) #define RT2860_TX_CFACK (1 << 2) #define RT2860_TX_MMPS (1 << 1) #define RT2860_TX_FRAG (1 << 0) uint8_t txop; #define RT2860_TX_TXOP_HT 0 #define RT2860_TX_TXOP_PIFS 1 #define RT2860_TX_TXOP_SIFS 2 #define RT2860_TX_TXOP_BACKOFF 3 uint16_t phy; #define RT2860_PHY_MODE 0xc000 #define RT2860_PHY_CCK (0 << 14) #define RT2860_PHY_OFDM (1 << 14) #define RT2860_PHY_HT (2 << 14) #define RT2860_PHY_HT_GF (3 << 14) #define RT2860_PHY_SGI (1 << 8) #define RT2860_PHY_BW40 (1 << 7) #define RT2860_PHY_MCS 0x7f #define RT2860_PHY_SHPRE (1 << 3) uint8_t xflags; #define RT2860_TX_BAWINSIZE_SHIFT 2 #define RT2860_TX_NSEQ (1 << 1) #define RT2860_TX_ACK (1 << 0) uint8_t wcid; /* Wireless Client ID */ uint16_t len; #define RT2860_TX_PID_SHIFT 12 uint32_t iv; uint32_t eiv; } __packed; /* RT2860 RX descriptor */ struct rt2860_rxd { uint32_t sdp0; uint16_t sdl1; /* unused */ uint16_t sdl0; #define RT2860_RX_DDONE (1 << 15) #define RT2860_RX_LS0 (1 << 14) uint32_t sdp1; /* unused */ uint32_t flags; #define RT2860_RX_DEC (1 << 16) #define RT2860_RX_AMPDU (1 << 15) #define RT2860_RX_L2PAD (1 << 14) #define RT2860_RX_RSSI (1 << 13) #define RT2860_RX_HTC (1 << 12) #define RT2860_RX_AMSDU (1 << 11) #define RT2860_RX_MICERR (1 << 10) #define RT2860_RX_ICVERR (1 << 9) #define RT2860_RX_CRCERR (1 << 8) #define RT2860_RX_MYBSS (1 << 7) #define RT2860_RX_BC (1 << 6) #define RT2860_RX_MC (1 << 5) #define RT2860_RX_UC2ME (1 << 4) #define RT2860_RX_FRAG (1 << 3) #define RT2860_RX_NULL (1 << 2) #define RT2860_RX_DATA (1 << 1) #define RT2860_RX_BA (1 << 0) } __packed; /* RT2870 RX descriptor */ struct rt2870_rxd { /* single 32-bit field */ uint32_t flags; } __packed; /* RX Wireless Information */ struct rt2860_rxwi { uint8_t wcid; uint8_t keyidx; #define RT2860_RX_UDF_SHIFT 5 #define RT2860_RX_BSS_IDX_SHIFT 2 uint16_t len; #define RT2860_RX_TID_SHIFT 12 uint16_t seq; uint16_t phy; uint8_t rssi[3]; uint8_t reserved1; uint8_t snr[2]; uint16_t reserved2; } __packed; /* first DMA segment contains TXWI + 802.11 header + 32-bit padding */ #define RT2860_TXWI_DMASZ \ (sizeof (struct rt2860_txwi) + \ sizeof (struct ieee80211_frame) + 6 + \ sizeof (uint16_t)) #define RT2860_RF1 0 #define RT2860_RF2 2 #define RT2860_RF3 1 #define RT2860_RF4 3 -#define RT2860_RF_2820 1 /* 2T3R */ -#define RT2860_RF_2850 2 /* dual-band 2T3R */ -#define RT2860_RF_2720 3 /* 1T2R */ -#define RT2860_RF_2750 4 /* dual-band 1T2R */ -#define RT3070_RF_3020 5 /* 1T1R */ -#define RT3070_RF_2020 6 /* b/g */ -#define RT3070_RF_3021 7 /* 1T2R */ -#define RT3070_RF_3022 8 /* 2T2R */ -#define RT3070_RF_3052 9 /* dual-band 2T2R */ -#define RT3070_RF_3320 11 /* 1T1R */ -#define RT3070_RF_3053 13 /* dual-band 3T3R */ -#define RT5390_RF_5390 15 /* b/g/n */ +#define RT2860_RF_2820 0x0001 /* 2T3R */ +#define RT2860_RF_2850 0x0002 /* dual-band 2T3R */ +#define RT2860_RF_2720 0x0003 /* 1T2R */ +#define RT2860_RF_2750 0x0004 /* dual-band 1T2R */ +#define RT3070_RF_3020 0x0005 /* 1T1R */ +#define RT3070_RF_2020 0x0006 /* b/g */ +#define RT3070_RF_3021 0x0007 /* 1T2R */ +#define RT3070_RF_3022 0x0008 /* 2T2R */ +#define RT3070_RF_3052 0x0009 /* dual-band 2T2R */ +#define RT3070_RF_3320 0x000b /* 1T1R */ +#define RT3070_RF_3053 0x000d /* dual-band 3T3R */ +#define RT5390_RF_5360 0x5360 /* 1T1R */ +#define RT5390_RF_5390 0x5390 /* 1T1R */ /* USB commands for RT2870 only */ #define RT2870_RESET 1 #define RT2870_WRITE_2 2 #define RT2870_WRITE_REGION_1 6 #define RT2870_READ_REGION_1 7 #define RT2870_EEPROM_READ 9 #define RT2860_EEPROM_DELAY 1 /* minimum hold time (microsecond) */ +#define RT2860_EEPROM_CHIPID 0x00 #define RT2860_EEPROM_VERSION 0x01 #define RT2860_EEPROM_MAC01 0x02 #define RT2860_EEPROM_MAC23 0x03 #define RT2860_EEPROM_MAC45 0x04 #define RT2860_EEPROM_PCIE_PSLEVEL 0x11 #define RT2860_EEPROM_REV 0x12 #define RT2860_EEPROM_ANTENNA 0x1a #define RT2860_EEPROM_CONFIG 0x1b #define RT2860_EEPROM_COUNTRY 0x1c #define RT2860_EEPROM_FREQ_LEDS 0x1d #define RT2860_EEPROM_LED1 0x1e #define RT2860_EEPROM_LED2 0x1f #define RT2860_EEPROM_LED3 0x20 #define RT2860_EEPROM_LNA 0x22 #define RT2860_EEPROM_RSSI1_2GHZ 0x23 #define RT2860_EEPROM_RSSI2_2GHZ 0x24 #define RT2860_EEPROM_RSSI1_5GHZ 0x25 #define RT2860_EEPROM_RSSI2_5GHZ 0x26 #define RT2860_EEPROM_DELTAPWR 0x28 #define RT2860_EEPROM_PWR2GHZ_BASE1 0x29 #define RT2860_EEPROM_PWR2GHZ_BASE2 0x30 #define RT2860_EEPROM_TSSI1_2GHZ 0x37 #define RT2860_EEPROM_TSSI2_2GHZ 0x38 #define RT2860_EEPROM_TSSI3_2GHZ 0x39 #define RT2860_EEPROM_TSSI4_2GHZ 0x3a #define RT2860_EEPROM_TSSI5_2GHZ 0x3b #define RT2860_EEPROM_PWR5GHZ_BASE1 0x3c #define RT2860_EEPROM_PWR5GHZ_BASE2 0x53 #define RT2860_EEPROM_TSSI1_5GHZ 0x6a #define RT2860_EEPROM_TSSI2_5GHZ 0x6b #define RT2860_EEPROM_TSSI3_5GHZ 0x6c #define RT2860_EEPROM_TSSI4_5GHZ 0x6d #define RT2860_EEPROM_TSSI5_5GHZ 0x6e #define RT2860_EEPROM_RPWR 0x6f #define RT2860_EEPROM_BBP_BASE 0x78 #define RT3071_EEPROM_RF_BASE 0x82 #define RT2860_RIDX_CCK1 0 #define RT2860_RIDX_CCK11 3 #define RT2860_RIDX_OFDM6 4 #define RT2860_RIDX_MAX 11 static const struct rt2860_rate { uint8_t rate; uint8_t mcs; enum ieee80211_phytype phy; uint8_t ctl_ridx; uint16_t sp_ack_dur; uint16_t lp_ack_dur; } rt2860_rates[] = { { 2, 0, IEEE80211_T_DS, 0, 314, 314 }, { 4, 1, IEEE80211_T_DS, 1, 258, 162 }, { 11, 2, IEEE80211_T_DS, 2, 223, 127 }, { 22, 3, IEEE80211_T_DS, 3, 213, 117 }, { 12, 0, IEEE80211_T_OFDM, 4, 60, 60 }, { 18, 1, IEEE80211_T_OFDM, 4, 52, 52 }, { 24, 2, IEEE80211_T_OFDM, 6, 48, 48 }, { 36, 3, IEEE80211_T_OFDM, 6, 44, 44 }, { 48, 4, IEEE80211_T_OFDM, 8, 44, 44 }, { 72, 5, IEEE80211_T_OFDM, 8, 40, 40 }, { 96, 6, IEEE80211_T_OFDM, 8, 40, 40 }, { 108, 7, IEEE80211_T_OFDM, 8, 40, 40 } }; /* * Control and status registers access macros. */ #define RAL_READ(sc, reg) \ bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (reg)) #define RAL_WRITE(sc, reg, val) \ bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (reg), (val)) #define RAL_BARRIER_WRITE(sc) \ bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, 0x1800, \ BUS_SPACE_BARRIER_WRITE) #define RAL_BARRIER_READ_WRITE(sc) \ bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, 0x1800, \ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE) #define RAL_WRITE_REGION_1(sc, offset, datap, count) \ bus_space_write_region_1((sc)->sc_st, (sc)->sc_sh, (offset), \ (datap), (count)) #define RAL_SET_REGION_4(sc, offset, val, count) \ bus_space_set_region_4((sc)->sc_st, (sc)->sc_sh, (offset), \ (val), (count)) /* * EEPROM access macro. */ #define RT2860_EEPROM_CTL(sc, val) do { \ RAL_WRITE((sc), RT2860_PCI_EECTRL, (val)); \ RAL_BARRIER_READ_WRITE((sc)); \ DELAY(RT2860_EEPROM_DELAY); \ } while (/* CONSTCOND */0) /* * Default values for MAC registers; values taken from the reference driver. */ #define RT2860_DEF_MAC \ { RT2860_BCN_OFFSET0, 0xf8f0e8e0 }, \ { RT2860_BCN_OFFSET1, 0x6f77d0c8 }, \ { RT2860_LEGACY_BASIC_RATE, 0x0000013f }, \ { RT2860_HT_BASIC_RATE, 0x00008003 }, \ { RT2860_MAC_SYS_CTRL, 0x00000000 }, \ { RT2860_RX_FILTR_CFG, 0x00017f97 }, \ { RT2860_BKOFF_SLOT_CFG, 0x00000209 }, \ { RT2860_TX_SW_CFG0, 0x00000000 }, \ { RT2860_TX_SW_CFG1, 0x00080606 }, \ { RT2860_TX_LINK_CFG, 0x00001020 }, \ { RT2860_TX_TIMEOUT_CFG, 0x000a2090 }, \ { RT2860_MAX_LEN_CFG, 0x00001f00 }, \ { RT2860_LED_CFG, 0x7f031e46 }, \ { RT2860_WMM_AIFSN_CFG, 0x00002273 }, \ { RT2860_WMM_CWMIN_CFG, 0x00002344 }, \ { RT2860_WMM_CWMAX_CFG, 0x000034aa }, \ { RT2860_MAX_PCNT, 0x1f3fbf9f }, \ { RT2860_TX_RTY_CFG, 0x47d01f0f }, \ { RT2860_AUTO_RSP_CFG, 0x00000013 }, \ { RT2860_CCK_PROT_CFG, 0x05740003 }, \ { RT2860_OFDM_PROT_CFG, 0x05740003 }, \ { RT2860_GF20_PROT_CFG, 0x01744004 }, \ { RT2860_GF40_PROT_CFG, 0x03f44084 }, \ { RT2860_MM20_PROT_CFG, 0x01744004 }, \ { RT2860_MM40_PROT_CFG, 0x03f54084 }, \ { RT2860_TXOP_CTRL_CFG, 0x0000583f }, \ { RT2860_TX_RTS_CFG, 0x00092b20 }, \ { RT2860_EXP_ACK_TIME, 0x002400ca }, \ { RT2860_TXOP_HLDR_ET, 0x00000002 }, \ { RT2860_XIFS_TIME_CFG, 0x33a41010 }, \ { RT2860_PWR_PIN_CFG, 0x00000003 } /* * Default values for BBP registers; values taken from the reference driver. */ #define RT2860_DEF_BBP \ { 65, 0x2c }, \ { 66, 0x38 }, \ { 68, 0x0b }, \ { 69, 0x12 }, \ { 70, 0x0a }, \ { 73, 0x10 }, \ { 81, 0x37 }, \ { 82, 0x62 }, \ { 83, 0x6a }, \ { 84, 0x99 }, \ { 86, 0x00 }, \ { 91, 0x04 }, \ { 92, 0x00 }, \ { 103, 0x00 }, \ { 105, 0x05 }, \ { 106, 0x35 } #define RT5390_DEF_BBP \ { 31, 0x08 }, \ { 65, 0x2c }, \ { 66, 0x38 }, \ { 68, 0x0b }, \ { 69, 0x12 }, \ { 70, 0x0a }, \ { 73, 0x13 }, \ { 75, 0x46 }, \ { 76, 0x28 }, \ { 77, 0x59 }, \ { 81, 0x37 }, \ { 82, 0x62 }, \ { 83, 0x7a }, \ { 84, 0x19 }, \ { 86, 0x38 }, \ { 91, 0x04 }, \ { 92, 0x02 }, \ { 103, 0xc0 }, \ { 104, 0x92 }, \ { 105, 0x3c }, \ { 106, 0x03 }, \ { 128, 0x12 }, \ /* * Default settings for RF registers; values derived from the reference driver. */ #define RT2860_RF2850 \ { 1, 0x100bb3, 0x1301e1, 0x05a014, 0x001402 }, \ { 2, 0x100bb3, 0x1301e1, 0x05a014, 0x001407 }, \ { 3, 0x100bb3, 0x1301e2, 0x05a014, 0x001402 }, \ { 4, 0x100bb3, 0x1301e2, 0x05a014, 0x001407 }, \ { 5, 0x100bb3, 0x1301e3, 0x05a014, 0x001402 }, \ { 6, 0x100bb3, 0x1301e3, 0x05a014, 0x001407 }, \ { 7, 0x100bb3, 0x1301e4, 0x05a014, 0x001402 }, \ { 8, 0x100bb3, 0x1301e4, 0x05a014, 0x001407 }, \ { 9, 0x100bb3, 0x1301e5, 0x05a014, 0x001402 }, \ { 10, 0x100bb3, 0x1301e5, 0x05a014, 0x001407 }, \ { 11, 0x100bb3, 0x1301e6, 0x05a014, 0x001402 }, \ { 12, 0x100bb3, 0x1301e6, 0x05a014, 0x001407 }, \ { 13, 0x100bb3, 0x1301e7, 0x05a014, 0x001402 }, \ { 14, 0x100bb3, 0x1301e8, 0x05a014, 0x001404 }, \ { 36, 0x100bb3, 0x130266, 0x056014, 0x001408 }, \ { 38, 0x100bb3, 0x130267, 0x056014, 0x001404 }, \ { 40, 0x100bb2, 0x1301a0, 0x056014, 0x001400 }, \ { 44, 0x100bb2, 0x1301a0, 0x056014, 0x001408 }, \ { 46, 0x100bb2, 0x1301a1, 0x056014, 0x001402 }, \ { 48, 0x100bb2, 0x1301a1, 0x056014, 0x001406 }, \ { 52, 0x100bb2, 0x1301a2, 0x056014, 0x001404 }, \ { 54, 0x100bb2, 0x1301a2, 0x056014, 0x001408 }, \ { 56, 0x100bb2, 0x1301a3, 0x056014, 0x001402 }, \ { 60, 0x100bb2, 0x1301a4, 0x056014, 0x001400 }, \ { 62, 0x100bb2, 0x1301a4, 0x056014, 0x001404 }, \ { 64, 0x100bb2, 0x1301a4, 0x056014, 0x001408 }, \ { 100, 0x100bb2, 0x1301ac, 0x05e014, 0x001400 }, \ { 102, 0x100bb2, 0x1701ac, 0x15e014, 0x001404 }, \ { 104, 0x100bb2, 0x1701ac, 0x15e014, 0x001408 }, \ { 108, 0x100bb3, 0x17028c, 0x15e014, 0x001404 }, \ { 110, 0x100bb3, 0x13028d, 0x05e014, 0x001400 }, \ { 112, 0x100bb3, 0x13028d, 0x05e014, 0x001406 }, \ { 116, 0x100bb3, 0x13028e, 0x05e014, 0x001408 }, \ { 118, 0x100bb3, 0x13028f, 0x05e014, 0x001404 }, \ { 120, 0x100bb1, 0x1300e0, 0x05e014, 0x001400 }, \ { 124, 0x100bb1, 0x1300e0, 0x05e014, 0x001404 }, \ { 126, 0x100bb1, 0x1300e0, 0x05e014, 0x001406 }, \ { 128, 0x100bb1, 0x1300e0, 0x05e014, 0x001408 }, \ { 132, 0x100bb1, 0x1300e1, 0x05e014, 0x001402 }, \ { 134, 0x100bb1, 0x1300e1, 0x05e014, 0x001404 }, \ { 136, 0x100bb1, 0x1300e1, 0x05e014, 0x001406 }, \ { 140, 0x100bb1, 0x1300e2, 0x05e014, 0x001400 }, \ { 149, 0x100bb1, 0x1300e2, 0x05e014, 0x001409 }, \ { 151, 0x100bb1, 0x1300e3, 0x05e014, 0x001401 }, \ { 153, 0x100bb1, 0x1300e3, 0x05e014, 0x001403 }, \ { 157, 0x100bb1, 0x1300e3, 0x05e014, 0x001407 }, \ { 159, 0x100bb1, 0x1300e3, 0x05e014, 0x001409 }, \ { 161, 0x100bb1, 0x1300e4, 0x05e014, 0x001401 }, \ { 165, 0x100bb1, 0x1300e4, 0x05e014, 0x001405 }, \ { 167, 0x100bb1, 0x1300f4, 0x05e014, 0x001407 }, \ { 169, 0x100bb1, 0x1300f4, 0x05e014, 0x001409 }, \ { 171, 0x100bb1, 0x1300f5, 0x05e014, 0x001401 }, \ { 173, 0x100bb1, 0x1300f5, 0x05e014, 0x001403 } #define RT3070_RF3052 \ { 0xf1, 2, 2 }, \ { 0xf1, 2, 7 }, \ { 0xf2, 2, 2 }, \ { 0xf2, 2, 7 }, \ { 0xf3, 2, 2 }, \ { 0xf3, 2, 7 }, \ { 0xf4, 2, 2 }, \ { 0xf4, 2, 7 }, \ { 0xf5, 2, 2 }, \ { 0xf5, 2, 7 }, \ { 0xf6, 2, 2 }, \ { 0xf6, 2, 7 }, \ { 0xf7, 2, 2 }, \ { 0xf8, 2, 4 }, \ { 0x56, 0, 4 }, \ { 0x56, 0, 6 }, \ { 0x56, 0, 8 }, \ { 0x57, 0, 0 }, \ { 0x57, 0, 2 }, \ { 0x57, 0, 4 }, \ { 0x57, 0, 8 }, \ { 0x57, 0, 10 }, \ { 0x58, 0, 0 }, \ { 0x58, 0, 4 }, \ { 0x58, 0, 6 }, \ { 0x58, 0, 8 }, \ { 0x5b, 0, 8 }, \ { 0x5b, 0, 10 }, \ { 0x5c, 0, 0 }, \ { 0x5c, 0, 4 }, \ { 0x5c, 0, 6 }, \ { 0x5c, 0, 8 }, \ { 0x5d, 0, 0 }, \ { 0x5d, 0, 2 }, \ { 0x5d, 0, 4 }, \ { 0x5d, 0, 8 }, \ { 0x5d, 0, 10 }, \ { 0x5e, 0, 0 }, \ { 0x5e, 0, 4 }, \ { 0x5e, 0, 6 }, \ { 0x5e, 0, 8 }, \ { 0x5f, 0, 0 }, \ { 0x5f, 0, 9 }, \ { 0x5f, 0, 11 }, \ { 0x60, 0, 1 }, \ { 0x60, 0, 5 }, \ { 0x60, 0, 7 }, \ { 0x60, 0, 9 }, \ { 0x61, 0, 1 }, \ { 0x61, 0, 3 }, \ { 0x61, 0, 5 }, \ { 0x61, 0, 7 }, \ { 0x61, 0, 9 } #define RT3070_DEF_RF \ { 4, 0x40 }, \ { 5, 0x03 }, \ { 6, 0x02 }, \ { 7, 0x60 }, \ { 9, 0x0f }, \ { 10, 0x41 }, \ { 11, 0x21 }, \ { 12, 0x7b }, \ { 14, 0x90 }, \ { 15, 0x58 }, \ { 16, 0xb3 }, \ { 17, 0x92 }, \ { 18, 0x2c }, \ { 19, 0x02 }, \ { 20, 0xba }, \ { 21, 0xdb }, \ { 24, 0x16 }, \ { 25, 0x01 }, \ { 29, 0x1f } #define RT5390_DEF_RF \ { 1, 0x0f }, \ { 2, 0x80 }, \ { 3, 0x88 }, \ { 5, 0x10 }, \ { 6, 0xe0 }, \ { 7, 0x00 }, \ { 10, 0x53 }, \ { 11, 0x4a }, \ { 12, 0x46 }, \ { 13, 0x9f }, \ { 14, 0x00 }, \ { 15, 0x00 }, \ { 16, 0x00 }, \ { 18, 0x03 }, \ { 19, 0x00 }, \ { 20, 0x00 }, \ { 21, 0x00 }, \ { 22, 0x20 }, \ { 23, 0x00 }, \ { 24, 0x00 }, \ { 25, 0x80 }, \ { 26, 0x00 }, \ { 27, 0x09 }, \ { 28, 0x00 }, \ { 29, 0x10 }, \ { 30, 0x10 }, \ { 31, 0x80 }, \ { 32, 0x80 }, \ { 33, 0x00 }, \ { 34, 0x07 }, \ { 35, 0x12 }, \ { 36, 0x00 }, \ { 37, 0x08 }, \ { 38, 0x85 }, \ { 39, 0x1b }, \ { 40, 0x0b }, \ { 41, 0xbb }, \ { 42, 0xd2 }, \ { 43, 0x9a }, \ { 44, 0x0e }, \ { 45, 0xa2 }, \ { 46, 0x73 }, \ { 47, 0x00 }, \ { 48, 0x10 }, \ { 49, 0x94 }, \ { 52, 0x38 }, \ { 53, 0x00 }, \ { 54, 0x78 }, \ { 55, 0x23 }, \ { 56, 0x22 }, \ { 57, 0x80 }, \ { 58, 0x7f }, \ { 59, 0x07 }, \ { 60, 0x45 }, \ { 61, 0xd1 }, \ { 62, 0x00 }, \ { 63, 0x00 } #define RT5392_DEF_RF \ { 1, 0x17 }, \ { 2, 0x80 }, \ { 3, 0x88 }, \ { 5, 0x10 }, \ { 6, 0xe0 }, \ { 7, 0x00 }, \ { 10, 0x53 }, \ { 11, 0x4a }, \ { 12, 0x46 }, \ { 13, 0x9f }, \ { 14, 0x00 }, \ { 15, 0x00 }, \ { 16, 0x00 }, \ { 18, 0x03 }, \ { 19, 0x4d }, \ { 20, 0x00 }, \ { 21, 0x8d }, \ { 22, 0x20 }, \ { 23, 0x0b }, \ { 24, 0x44 }, \ { 25, 0x80 }, \ { 26, 0x82 }, \ { 27, 0x09 }, \ { 28, 0x00 }, \ { 29, 0x10 }, \ { 30, 0x10 }, \ { 31, 0x80 }, \ { 32, 0x80 }, \ { 33, 0xc0 }, \ { 34, 0x07 }, \ { 35, 0x12 }, \ { 36, 0x00 }, \ { 37, 0x08 }, \ { 38, 0x89 }, \ { 39, 0x1b }, \ { 40, 0x0f }, \ { 41, 0xbb }, \ { 42, 0xd5 }, \ { 43, 0x9b }, \ { 44, 0x0e }, \ { 45, 0xa2 }, \ { 46, 0x73 }, \ { 47, 0x0c }, \ { 48, 0x10 }, \ { 49, 0x94 }, \ { 50, 0x94 }, \ { 51, 0x3a }, \ { 52, 0x48 }, \ { 53, 0x44 }, \ { 54, 0x38 }, \ { 55, 0x43 }, \ { 56, 0xa1 }, \ { 57, 0x00 }, \ { 58, 0x39 }, \ { 59, 0x07 }, \ { 60, 0x45 }, \ { 61, 0x91 }, \ { 62, 0x39 }, \ { 63, 0x00 } Index: head/sys/dev/ral/rt2860var.h =================================================================== --- head/sys/dev/ral/rt2860var.h (revision 300005) +++ head/sys/dev/ral/rt2860var.h (revision 300006) @@ -1,209 +1,209 @@ /*- * Copyright (c) 2007 Damien Bergamini * Copyright (c) 2012 Bernhard Schmidt * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $OpenBSD: rt2860var.h,v 1.20 2010/09/07 16:21:42 deraadt Exp $ * $FreeBSD$ */ #define RT2860_TX_RING_COUNT 64 #define RT2860_RX_RING_COUNT 128 #define RT2860_TX_POOL_COUNT (RT2860_TX_RING_COUNT * 2) #define RT2860_MAX_SCATTER ((RT2860_TX_RING_COUNT * 2) - 1) /* HW supports up to 255 STAs */ #define RT2860_WCID_MAX 254 #define RT2860_AID2WCID(aid) ((aid) & 0xff) struct rt2860_rx_radiotap_header { struct ieee80211_radiotap_header wr_ihdr; uint64_t wr_tsf; uint8_t wr_flags; uint8_t wr_rate; uint16_t wr_chan_freq; uint16_t wr_chan_flags; uint8_t wr_antenna; int8_t wr_antsignal; int8_t wr_antnoise; } __packed; #define RT2860_RX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_TSFT) | \ (1 << IEEE80211_RADIOTAP_FLAGS) | \ (1 << IEEE80211_RADIOTAP_RATE) | \ (1 << IEEE80211_RADIOTAP_CHANNEL) | \ (1 << IEEE80211_RADIOTAP_ANTENNA) | \ (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \ (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE)) struct rt2860_tx_radiotap_header { struct ieee80211_radiotap_header wt_ihdr; uint8_t wt_flags; uint8_t wt_rate; uint16_t wt_chan_freq; uint16_t wt_chan_flags; } __packed; #define RT2860_TX_RADIOTAP_PRESENT \ ((1 << IEEE80211_RADIOTAP_FLAGS) | \ (1 << IEEE80211_RADIOTAP_RATE) | \ (1 << IEEE80211_RADIOTAP_CHANNEL)) struct rt2860_tx_data { struct rt2860_txwi *txwi; struct mbuf *m; struct ieee80211_node *ni; bus_dmamap_t map; bus_addr_t paddr; SLIST_ENTRY(rt2860_tx_data) next; }; struct rt2860_tx_ring { struct rt2860_txd *txd; bus_addr_t paddr; bus_dma_tag_t desc_dmat; bus_dmamap_t desc_map; bus_dma_segment_t seg; struct rt2860_tx_data *data[RT2860_TX_RING_COUNT]; int cur; int next; int queued; }; struct rt2860_rx_data { struct mbuf *m; bus_dmamap_t map; }; struct rt2860_rx_ring { struct rt2860_rxd *rxd; bus_addr_t paddr; bus_dma_tag_t desc_dmat; bus_dmamap_t desc_map; bus_dma_tag_t data_dmat; bus_dma_segment_t seg; unsigned int cur; /* must be unsigned */ struct rt2860_rx_data data[RT2860_RX_RING_COUNT]; }; struct rt2860_node { struct ieee80211_node ni; uint8_t wcid; uint8_t ridx[IEEE80211_RATE_MAXSIZE]; uint8_t ctl_ridx[IEEE80211_RATE_MAXSIZE]; }; struct rt2860_vap { struct ieee80211vap ral_vap; int (*ral_newstate)(struct ieee80211vap *, enum ieee80211_state, int); }; #define RT2860_VAP(vap) ((struct rt2860_vap *)(vap)) struct rt2860_softc { struct ieee80211com sc_ic; struct mbufq sc_snd; struct mtx sc_mtx; device_t sc_dev; bus_space_tag_t sc_st; bus_space_handle_t sc_sh; struct callout watchdog_ch; int sc_invalid; int sc_debug; /* * The same in both up to here * ------------------------------------------------ */ uint16_t (*sc_srom_read)(struct rt2860_softc *, uint16_t); void (*sc_node_free)(struct ieee80211_node *); int sc_flags; #define RT2860_ENABLED (1 << 0) #define RT2860_ADVANCED_PS (1 << 1) #define RT2860_PCIE (1 << 2) #define RT2860_RUNNING (1 << 3) struct ieee80211_node *wcid2ni[RT2860_WCID_MAX]; struct rt2860_tx_ring txq[6]; struct rt2860_rx_ring rxq; SLIST_HEAD(, rt2860_tx_data) data_pool; struct rt2860_tx_data data[RT2860_TX_POOL_COUNT]; bus_dma_tag_t txwi_dmat; bus_dmamap_t txwi_map; bus_dma_segment_t txwi_seg; caddr_t txwi_vaddr; int sc_tx_timer; int mgtqid; uint8_t qfullmsk; uint16_t mac_ver; uint16_t mac_rev; - uint8_t rf_rev; + uint16_t rf_rev; uint8_t freq; uint8_t ntxchains; uint8_t nrxchains; uint8_t pslevel; int8_t txpow1[54]; int8_t txpow2[54]; int8_t rssi_2ghz[3]; int8_t rssi_5ghz[3]; uint8_t lna[4]; uint8_t rf24_20mhz; uint8_t rf24_40mhz; uint8_t patch_dac; uint8_t rfswitch; uint8_t ext_2ghz_lna; uint8_t ext_5ghz_lna; uint8_t calib_2ghz; uint8_t calib_5ghz; uint8_t txmixgain_2ghz; uint8_t txmixgain_5ghz; uint8_t tssi_2ghz[9]; uint8_t tssi_5ghz[9]; uint8_t step_2ghz; uint8_t step_5ghz; struct { uint8_t reg; uint8_t val; } bbp[8], rf[10]; uint8_t leds; uint16_t led[3]; uint32_t txpow20mhz[5]; uint32_t txpow40mhz_2ghz[5]; uint32_t txpow40mhz_5ghz[5]; struct rt2860_rx_radiotap_header sc_rxtap; struct rt2860_tx_radiotap_header sc_txtap; }; int rt2860_attach(device_t, int); int rt2860_detach(void *); void rt2860_shutdown(void *); void rt2860_suspend(void *); void rt2860_resume(void *); void rt2860_intr(void *); #define RAL_LOCK(sc) mtx_lock(&(sc)->sc_mtx) #define RAL_LOCK_ASSERT(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED) #define RAL_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)