rt2661.c revision 190532
1141104Sharti/* $FreeBSD: head/sys/dev/ral/rt2661.c 190532 2009-03-29 21:17:08Z sam $ */ 21590Srgrimes 31590Srgrimes/*- 41590Srgrimes * Copyright (c) 2006 51590Srgrimes * Damien Bergamini <damien.bergamini@free.fr> 61590Srgrimes * 71590Srgrimes * Permission to use, copy, modify, and distribute this software for any 81590Srgrimes * purpose with or without fee is hereby granted, provided that the above 91590Srgrimes * copyright notice and this permission notice appear in all copies. 101590Srgrimes * 111590Srgrimes * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 121590Srgrimes * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 131590Srgrimes * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 141590Srgrimes * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 151590Srgrimes * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 161590Srgrimes * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 171590Srgrimes * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 181590Srgrimes */ 191590Srgrimes 201590Srgrimes#include <sys/cdefs.h> 211590Srgrimes__FBSDID("$FreeBSD: head/sys/dev/ral/rt2661.c 190532 2009-03-29 21:17:08Z sam $"); 221590Srgrimes 231590Srgrimes/*- 241590Srgrimes * Ralink Technology RT2561, RT2561S and RT2661 chipset driver 251590Srgrimes * http://www.ralinktech.com/ 261590Srgrimes */ 271590Srgrimes 281590Srgrimes#include <sys/param.h> 291590Srgrimes#include <sys/sysctl.h> 301590Srgrimes#include <sys/sockio.h> 311590Srgrimes#include <sys/mbuf.h> 321590Srgrimes#include <sys/kernel.h> 331590Srgrimes#include <sys/socket.h> 341590Srgrimes#include <sys/systm.h> 351590Srgrimes#include <sys/malloc.h> 361590Srgrimes#include <sys/lock.h> 3762833Swsanchez#include <sys/mutex.h> 3862833Swsanchez#include <sys/module.h> 391590Srgrimes#include <sys/bus.h> 401590Srgrimes#include <sys/endian.h> 4162833Swsanchez#include <sys/firmware.h> 4294587Sobrien 431590Srgrimes#include <machine/bus.h> 441590Srgrimes#include <machine/resource.h> 451590Srgrimes#include <sys/rman.h> 461590Srgrimes 471590Srgrimes#include <net/bpf.h> 481590Srgrimes#include <net/if.h> 491590Srgrimes#include <net/if_arp.h> 501590Srgrimes#include <net/ethernet.h> 511590Srgrimes#include <net/if_dl.h> 521590Srgrimes#include <net/if_media.h> 531590Srgrimes#include <net/if_types.h> 541590Srgrimes 551590Srgrimes#include <net80211/ieee80211_var.h> 561590Srgrimes#include <net80211/ieee80211_radiotap.h> 571590Srgrimes#include <net80211/ieee80211_regdomain.h> 581590Srgrimes#include <net80211/ieee80211_amrr.h> 591590Srgrimes 601590Srgrimes#include <netinet/in.h> 611590Srgrimes#include <netinet/in_systm.h> 621590Srgrimes#include <netinet/in_var.h> 631590Srgrimes#include <netinet/ip.h> 641590Srgrimes#include <netinet/if_ether.h> 651590Srgrimes 661590Srgrimes#include <dev/ral/rt2661reg.h> 671590Srgrimes#include <dev/ral/rt2661var.h> 681590Srgrimes 691590Srgrimes#define RAL_DEBUG 701590Srgrimes#ifdef RAL_DEBUG 711590Srgrimes#define DPRINTF(sc, fmt, ...) do { \ 721590Srgrimes if (sc->sc_debug > 0) \ 731590Srgrimes printf(fmt, __VA_ARGS__); \ 741590Srgrimes} while (0) 751590Srgrimes#define DPRINTFN(sc, n, fmt, ...) do { \ 761590Srgrimes if (sc->sc_debug >= (n)) \ 771590Srgrimes printf(fmt, __VA_ARGS__); \ 781590Srgrimes} while (0) 791590Srgrimes#else 801590Srgrimes#define DPRINTF(sc, fmt, ...) 811590Srgrimes#define DPRINTFN(sc, n, fmt, ...) 821590Srgrimes#endif 831590Srgrimes 841590Srgrimesstatic struct ieee80211vap *rt2661_vap_create(struct ieee80211com *, 851590Srgrimes const char name[IFNAMSIZ], int unit, int opmode, 861590Srgrimes int flags, const uint8_t bssid[IEEE80211_ADDR_LEN], 871590Srgrimes const uint8_t mac[IEEE80211_ADDR_LEN]); 881590Srgrimesstatic void rt2661_vap_delete(struct ieee80211vap *); 8969527Swillstatic void rt2661_dma_map_addr(void *, bus_dma_segment_t *, int, 901590Srgrimes int); 911590Srgrimesstatic int rt2661_alloc_tx_ring(struct rt2661_softc *, 921590Srgrimes struct rt2661_tx_ring *, int); 93144020Shartistatic void rt2661_reset_tx_ring(struct rt2661_softc *, 94143807Sharti struct rt2661_tx_ring *); 95141104Shartistatic void rt2661_free_tx_ring(struct rt2661_softc *, 96141104Sharti struct rt2661_tx_ring *); 971590Srgrimesstatic int rt2661_alloc_rx_ring(struct rt2661_softc *, 98141104Sharti struct rt2661_rx_ring *, int); 99142457Shartistatic void rt2661_reset_rx_ring(struct rt2661_softc *, 100141104Sharti struct rt2661_rx_ring *); 101141104Shartistatic void rt2661_free_rx_ring(struct rt2661_softc *, 102141104Sharti struct rt2661_rx_ring *); 103141104Shartistatic struct ieee80211_node *rt2661_node_alloc(struct ieee80211vap *, 104141104Sharti const uint8_t [IEEE80211_ADDR_LEN]); 105141104Shartistatic void rt2661_newassoc(struct ieee80211_node *, int); 106141104Shartistatic int rt2661_newstate(struct ieee80211vap *, 107141104Sharti enum ieee80211_state, int); 108141104Shartistatic uint16_t rt2661_eeprom_read(struct rt2661_softc *, uint8_t); 109141104Shartistatic void rt2661_rx_intr(struct rt2661_softc *); 110141104Shartistatic void rt2661_tx_intr(struct rt2661_softc *); 111141104Shartistatic void rt2661_tx_dma_intr(struct rt2661_softc *, 112141104Sharti struct rt2661_tx_ring *); 113138916Shartistatic void rt2661_mcu_beacon_expire(struct rt2661_softc *); 114138916Shartistatic void rt2661_mcu_wakeup(struct rt2661_softc *); 1151590Srgrimesstatic void rt2661_mcu_cmd_intr(struct rt2661_softc *); 116138916Shartistatic void rt2661_scan_start(struct ieee80211com *); 117138916Shartistatic void rt2661_scan_end(struct ieee80211com *); 118138916Shartistatic void rt2661_set_channel(struct ieee80211com *); 119138916Shartistatic void rt2661_setup_tx_desc(struct rt2661_softc *, 120138916Sharti struct rt2661_tx_desc *, uint32_t, uint16_t, int, 121138916Sharti int, const bus_dma_segment_t *, int, int); 122138916Shartistatic int rt2661_tx_data(struct rt2661_softc *, struct mbuf *, 123138916Sharti struct ieee80211_node *, int); 124138916Shartistatic int rt2661_tx_mgt(struct rt2661_softc *, struct mbuf *, 125143407Sharti struct ieee80211_node *); 126143407Shartistatic void rt2661_start_locked(struct ifnet *); 1271590Srgrimesstatic void rt2661_start(struct ifnet *); 1281590Srgrimesstatic int rt2661_raw_xmit(struct ieee80211_node *, struct mbuf *, 1291590Srgrimes const struct ieee80211_bpf_params *); 1301590Srgrimesstatic void rt2661_watchdog(void *); 131143411Shartistatic int rt2661_ioctl(struct ifnet *, u_long, caddr_t); 132143407Shartistatic void rt2661_bbp_write(struct rt2661_softc *, uint8_t, 133143407Sharti uint8_t); 134143407Shartistatic uint8_t rt2661_bbp_read(struct rt2661_softc *, uint8_t); 135143407Shartistatic void rt2661_rf_write(struct rt2661_softc *, uint8_t, 136143407Sharti uint32_t); 137143407Shartistatic int rt2661_tx_cmd(struct rt2661_softc *, uint8_t, 138144020Sharti uint16_t); 139143407Shartistatic void rt2661_select_antenna(struct rt2661_softc *); 140143407Shartistatic void rt2661_enable_mrr(struct rt2661_softc *); 141143407Shartistatic void rt2661_set_txpreamble(struct rt2661_softc *); 142143407Shartistatic void rt2661_set_basicrates(struct rt2661_softc *, 143143407Sharti const struct ieee80211_rateset *); 1441590Srgrimesstatic void rt2661_select_band(struct rt2661_softc *, 1451590Srgrimes struct ieee80211_channel *); 1461590Srgrimesstatic void rt2661_set_chan(struct rt2661_softc *, 1471590Srgrimes struct ieee80211_channel *); 1481590Srgrimesstatic void rt2661_set_bssid(struct rt2661_softc *, 149143411Sharti const uint8_t *); 150143407Shartistatic void rt2661_set_macaddr(struct rt2661_softc *, 151143407Sharti const uint8_t *); 152143407Shartistatic void rt2661_update_promisc(struct ifnet *); 153143411Shartistatic int rt2661_wme_update(struct ieee80211com *) __unused; 154143407Shartistatic void rt2661_update_slot(struct ifnet *); 155143407Shartistatic const char *rt2661_get_rf(int); 1561590Srgrimesstatic void rt2661_read_eeprom(struct rt2661_softc *, 1575814Sjkh uint8_t macaddr[IEEE80211_ADDR_LEN]); 158143407Shartistatic int rt2661_bbp_init(struct rt2661_softc *); 1595814Sjkhstatic void rt2661_init_locked(struct rt2661_softc *); 1601590Srgrimesstatic void rt2661_init(void *); 1611590Srgrimesstatic void rt2661_stop_locked(struct rt2661_softc *); 162143407Shartistatic void rt2661_stop(void *); 163143407Shartistatic int rt2661_load_microcode(struct rt2661_softc *); 1641590Srgrimes#ifdef notyet 165143407Shartistatic void rt2661_rx_tune(struct rt2661_softc *); 166143407Shartistatic void rt2661_radar_start(struct rt2661_softc *); 1671590Srgrimesstatic int rt2661_radar_stop(struct rt2661_softc *); 168138512Sharti#endif 1691590Srgrimesstatic int rt2661_prepare_beacon(struct rt2661_softc *, 170141271Sharti struct ieee80211vap *); 1711590Srgrimesstatic void rt2661_enable_tsf_sync(struct rt2661_softc *); 1721590Srgrimesstatic int rt2661_get_rssi(struct rt2661_softc *, uint8_t); 1731590Srgrimes 174143807Shartistatic const struct { 1751590Srgrimes uint32_t reg; 1761590Srgrimes uint32_t val; 1771590Srgrimes} rt2661_def_mac[] = { 1781590Srgrimes RT2661_DEF_MAC 1791590Srgrimes}; 1801590Srgrimes 1811590Srgrimesstatic const struct { 1821590Srgrimes uint8_t reg; 1831590Srgrimes uint8_t val; 1841590Srgrimes} rt2661_def_bbp[] = { 185138561Sharti RT2661_DEF_BBP 1861590Srgrimes}; 187143407Sharti 188143407Shartistatic const struct rfprog { 189143807Sharti uint8_t chan; 1901590Srgrimes uint32_t r1, r2, r3, r4; 191143807Sharti} rt2661_rf5225_1[] = { 192143407Sharti RT2661_RF5225_1 193143807Sharti}, rt2661_rf5225_2[] = { 1941590Srgrimes RT2661_RF5225_2 195143807Sharti}; 196143407Sharti 197143407Shartiint 198143807Shartirt2661_attach(device_t dev, int id) 199143407Sharti{ 2001590Srgrimes struct rt2661_softc *sc = device_get_softc(dev); 201143407Sharti struct ieee80211com *ic; 2021590Srgrimes struct ifnet *ifp; 2031590Srgrimes uint32_t val; 2041590Srgrimes int error, ac, ntries; 2051590Srgrimes uint8_t bands; 206143911Sharti uint8_t macaddr[IEEE80211_ADDR_LEN]; 207143911Sharti 2081590Srgrimes sc->sc_id = id; 2091590Srgrimes sc->sc_dev = dev; 210143911Sharti 2111590Srgrimes ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211); 2121590Srgrimes if (ifp == NULL) { 2131590Srgrimes device_printf(sc->sc_dev, "can not if_alloc()\n"); 2141590Srgrimes return ENOMEM; 2151590Srgrimes } 216143911Sharti ic = ifp->if_l2com; 217143911Sharti 2181590Srgrimes mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, 219143911Sharti MTX_DEF | MTX_RECURSE); 220138232Sharti 221143911Sharti callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0); 222143911Sharti 223143911Sharti /* wait for NIC to initialize */ 224143911Sharti for (ntries = 0; ntries < 1000; ntries++) { 225143911Sharti if ((val = RAL_READ(sc, RT2661_MAC_CSR0)) != 0) 2261590Srgrimes break; 2271590Srgrimes DELAY(1000); 2281590Srgrimes } 2291590Srgrimes if (ntries == 1000) { 230143911Sharti device_printf(sc->sc_dev, 231143911Sharti "timeout waiting for NIC to initialize\n"); 2321590Srgrimes error = EIO; 2331590Srgrimes goto fail1; 234143911Sharti } 2351590Srgrimes 2361590Srgrimes /* retrieve RF rev. no and various other things from EEPROM */ 2371590Srgrimes rt2661_read_eeprom(sc, macaddr); 2381590Srgrimes 2391590Srgrimes device_printf(dev, "MAC/BBP RT%X, RF %s\n", val, 240143911Sharti rt2661_get_rf(sc->rf_rev)); 241143911Sharti 2421590Srgrimes /* 243143911Sharti * Allocate Tx and Rx rings. 244138232Sharti */ 245143911Sharti for (ac = 0; ac < 4; ac++) { 246143911Sharti error = rt2661_alloc_tx_ring(sc, &sc->txq[ac], 247143911Sharti RT2661_TX_RING_COUNT); 248138561Sharti if (error != 0) { 249143911Sharti device_printf(sc->sc_dev, 2501590Srgrimes "could not allocate Tx ring %d\n", ac); 2511590Srgrimes goto fail2; 2521590Srgrimes } 2535814Sjkh } 254138972Sharti 255138972Sharti error = rt2661_alloc_tx_ring(sc, &sc->mgtq, RT2661_MGT_RING_COUNT); 256138972Sharti if (error != 0) { 257138972Sharti device_printf(sc->sc_dev, "could not allocate Mgt ring\n"); 258138972Sharti goto fail2; 2591590Srgrimes } 2601590Srgrimes 2611590Srgrimes error = rt2661_alloc_rx_ring(sc, &sc->rxq, RT2661_RX_RING_COUNT); 2621590Srgrimes if (error != 0) { 2631590Srgrimes device_printf(sc->sc_dev, "could not allocate Rx ring\n"); 2641590Srgrimes goto fail3; 2651590Srgrimes } 2661590Srgrimes 2671590Srgrimes ifp->if_softc = sc; 2681590Srgrimes if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 2691590Srgrimes ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 2701590Srgrimes ifp->if_init = rt2661_init; 2711590Srgrimes ifp->if_ioctl = rt2661_ioctl; 272138232Sharti ifp->if_start = rt2661_start; 2731590Srgrimes IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); 274143407Sharti ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; 2755814Sjkh IFQ_SET_READY(&ifp->if_snd); 276143407Sharti 277143407Sharti ic->ic_ifp = ifp; 2785814Sjkh ic->ic_opmode = IEEE80211_M_STA; 279143407Sharti ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ 280143407Sharti 2815814Sjkh /* set device capabilities */ 282143407Sharti ic->ic_caps = 283143407Sharti IEEE80211_C_STA /* station mode */ 284143407Sharti | IEEE80211_C_IBSS /* ibss, nee adhoc, mode */ 285143407Sharti | IEEE80211_C_HOSTAP /* hostap mode */ 2865814Sjkh | IEEE80211_C_MONITOR /* monitor mode */ 287143407Sharti | IEEE80211_C_AHDEMO /* adhoc demo mode */ 288143407Sharti | IEEE80211_C_WDS /* 4-address traffic works */ 2891590Srgrimes | IEEE80211_C_SHPREAMBLE /* short preamble supported */ 290138972Sharti | IEEE80211_C_SHSLOT /* short slot time supported */ 2911590Srgrimes | IEEE80211_C_WPA /* capable of WPA1+WPA2 */ 2921590Srgrimes | IEEE80211_C_BGSCAN /* capable of bg scanning */ 2931590Srgrimes#ifdef notyet 2945814Sjkh | IEEE80211_C_TXFRAG /* handle tx frags */ 2955814Sjkh | IEEE80211_C_WME /* 802.11e */ 2965814Sjkh#endif 2975814Sjkh ; 2985814Sjkh 2995814Sjkh bands = 0; 3005814Sjkh setbit(&bands, IEEE80211_MODE_11B); 30135464Sphk setbit(&bands, IEEE80211_MODE_11G); 3025814Sjkh if (sc->rf_rev == RT2661_RF_5225 || sc->rf_rev == RT2661_RF_5325) 3035814Sjkh setbit(&bands, IEEE80211_MODE_11A); 3045814Sjkh ieee80211_init_channels(ic, NULL, &bands); 305138512Sharti 3065814Sjkh ieee80211_ifattach(ic, macaddr); 307143407Sharti ic->ic_newassoc = rt2661_newassoc; 308138264Sharti ic->ic_node_alloc = rt2661_node_alloc; 309143407Sharti#if 0 310143407Sharti ic->ic_wme.wme_update = rt2661_wme_update; 311143407Sharti#endif 312143407Sharti ic->ic_scan_start = rt2661_scan_start; 3135814Sjkh ic->ic_scan_end = rt2661_scan_end; 314138232Sharti ic->ic_set_channel = rt2661_set_channel; 3155814Sjkh ic->ic_updateslot = rt2661_update_slot; 3165814Sjkh ic->ic_update_promisc = rt2661_update_promisc; 3171590Srgrimes ic->ic_raw_xmit = rt2661_raw_xmit; 3181590Srgrimes 3191590Srgrimes ic->ic_vap_create = rt2661_vap_create; 3201590Srgrimes ic->ic_vap_delete = rt2661_vap_delete; 3211590Srgrimes 3221590Srgrimes bpfattach(ifp, DLT_IEEE802_11_RADIO, 3231590Srgrimes sizeof (struct ieee80211_frame) + sizeof (sc->sc_txtap)); 3241590Srgrimes 3255814Sjkh sc->sc_rxtap_len = sizeof sc->sc_rxtap; 3261590Srgrimes sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len); 3271590Srgrimes sc->sc_rxtap.wr_ihdr.it_present = htole32(RT2661_RX_RADIOTAP_PRESENT); 3281590Srgrimes 329138512Sharti sc->sc_txtap_len = sizeof sc->sc_txtap; 3301590Srgrimes sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len); 331143407Sharti sc->sc_txtap.wt_ihdr.it_present = htole32(RT2661_TX_RADIOTAP_PRESENT); 332143407Sharti 3331590Srgrimes#ifdef RAL_DEBUG 334143407Sharti SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), 335143407Sharti SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 336143407Sharti "debug", CTLFLAG_RW, &sc->sc_debug, 0, "debug msgs"); 337143407Sharti#endif 338143407Sharti if (bootverbose) 339143407Sharti ieee80211_announce(ic); 340143407Sharti 341143407Sharti return 0; 342143407Sharti 3431590Srgrimesfail3: rt2661_free_tx_ring(sc, &sc->mgtq); 344143407Shartifail2: while (--ac >= 0) 345143407Sharti rt2661_free_tx_ring(sc, &sc->txq[ac]); 346143407Shartifail1: mtx_destroy(&sc->sc_mtx); 347143407Sharti if_free(ifp); 348143407Sharti return error; 349143407Sharti} 350143407Sharti 351143407Shartiint 352143407Shartirt2661_detach(void *xsc) 353143407Sharti{ 354143407Sharti struct rt2661_softc *sc = xsc; 355143407Sharti struct ifnet *ifp = sc->sc_ifp; 356143407Sharti struct ieee80211com *ic = ifp->if_l2com; 357143407Sharti 3581590Srgrimes RAL_LOCK(sc); 3591590Srgrimes rt2661_stop_locked(sc); 3601590Srgrimes RAL_UNLOCK(sc); 3611590Srgrimes 3621590Srgrimes bpfdetach(ifp); 3631590Srgrimes ieee80211_ifdetach(ic); 3641590Srgrimes 3651590Srgrimes rt2661_free_tx_ring(sc, &sc->txq[0]); 3661590Srgrimes rt2661_free_tx_ring(sc, &sc->txq[1]); 3671590Srgrimes rt2661_free_tx_ring(sc, &sc->txq[2]); 3681590Srgrimes rt2661_free_tx_ring(sc, &sc->txq[3]); 3691590Srgrimes rt2661_free_tx_ring(sc, &sc->mgtq); 3701590Srgrimes rt2661_free_rx_ring(sc, &sc->rxq); 3711590Srgrimes 3721590Srgrimes if_free(ifp); 3731590Srgrimes 3741590Srgrimes mtx_destroy(&sc->sc_mtx); 3751590Srgrimes 3761590Srgrimes return 0; 3771590Srgrimes} 378138232Sharti 3791590Srgrimesstatic struct ieee80211vap * 380138232Shartirt2661_vap_create(struct ieee80211com *ic, 381143407Sharti const char name[IFNAMSIZ], int unit, int opmode, int flags, 382138916Sharti const uint8_t bssid[IEEE80211_ADDR_LEN], 383143407Sharti const uint8_t mac[IEEE80211_ADDR_LEN]) 384143407Sharti{ 385143407Sharti struct ifnet *ifp = ic->ic_ifp; 386143407Sharti struct rt2661_vap *rvp; 387143407Sharti struct ieee80211vap *vap; 388143407Sharti 389143407Sharti switch (opmode) { 390143407Sharti case IEEE80211_M_STA: 391143407Sharti case IEEE80211_M_IBSS: 3921590Srgrimes case IEEE80211_M_AHDEMO: 3931590Srgrimes case IEEE80211_M_MONITOR: 3941590Srgrimes case IEEE80211_M_HOSTAP: 3951590Srgrimes if (!TAILQ_EMPTY(&ic->ic_vaps)) { 3961590Srgrimes if_printf(ifp, "only 1 vap supported\n"); 3971590Srgrimes return NULL; 3981590Srgrimes } 3991590Srgrimes if (opmode == IEEE80211_M_STA) 4001590Srgrimes flags |= IEEE80211_CLONE_NOBEACONS; 4011590Srgrimes break; 4021590Srgrimes case IEEE80211_M_WDS: 4031590Srgrimes if (TAILQ_EMPTY(&ic->ic_vaps) || 4041590Srgrimes ic->ic_opmode != IEEE80211_M_HOSTAP) { 4051590Srgrimes if_printf(ifp, "wds only supported in ap mode\n"); 4061590Srgrimes return NULL; 4071590Srgrimes } 408104696Sjmallett /* 4091590Srgrimes * Silently remove any request for a unique 410143407Sharti * bssid; WDS vap's always share the local 411143407Sharti * mac address. 412143407Sharti */ 413143407Sharti flags &= ~IEEE80211_CLONE_BSSID; 414143407Sharti break; 415143407Sharti default: 416143407Sharti if_printf(ifp, "unknown opmode %d\n", opmode); 4171590Srgrimes return NULL; 418143407Sharti } 4198874Srgrimes rvp = (struct rt2661_vap *) malloc(sizeof(struct rt2661_vap), 420143407Sharti M_80211_VAP, M_NOWAIT | M_ZERO); 421143407Sharti if (rvp == NULL) 422143407Sharti return NULL; 423143407Sharti vap = &rvp->ral_vap; 424143407Sharti ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac); 425143407Sharti 426143911Sharti /* override state transition machine */ 427143407Sharti rvp->ral_newstate = vap->iv_newstate; 428143911Sharti vap->iv_newstate = rt2661_newstate; 429143911Sharti#if 0 430143911Sharti vap->iv_update_beacon = rt2661_beacon_update; 431143911Sharti#endif 432143911Sharti 433143911Sharti ieee80211_amrr_init(&rvp->amrr, vap, 434143407Sharti IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD, 435143911Sharti IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD, 436143407Sharti 500 /* ms */); 437143407Sharti 438143407Sharti /* complete setup */ 439143407Sharti ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status); 440143407Sharti if (TAILQ_FIRST(&ic->ic_vaps) == vap) 441143407Sharti ic->ic_opmode = opmode; 442143407Sharti return vap; 443143407Sharti} 444143407Sharti 445143407Shartistatic void 446143407Shartirt2661_vap_delete(struct ieee80211vap *vap) 447143407Sharti{ 448143407Sharti struct rt2661_vap *rvp = RT2661_VAP(vap); 449143407Sharti 450143407Sharti ieee80211_amrr_cleanup(&rvp->amrr); 451143407Sharti ieee80211_vap_detach(vap); 452143407Sharti free(rvp, M_80211_VAP); 453143407Sharti} 454143407Sharti 455143407Shartivoid 456143407Shartirt2661_shutdown(void *xsc) 457143407Sharti{ 458143407Sharti struct rt2661_softc *sc = xsc; 459143407Sharti 460143407Sharti rt2661_stop(sc); 461143407Sharti} 462143911Sharti 463143911Shartivoid 464143911Shartirt2661_suspend(void *xsc) 465143407Sharti{ 466143407Sharti struct rt2661_softc *sc = xsc; 467143407Sharti 468143407Sharti rt2661_stop(sc); 469143911Sharti} 470143911Sharti 4711590Srgrimesvoid 4721590Srgrimesrt2661_resume(void *xsc) 4731590Srgrimes{ 4741590Srgrimes struct rt2661_softc *sc = xsc; 4751590Srgrimes struct ifnet *ifp = sc->sc_ifp; 4761590Srgrimes 4771590Srgrimes if (ifp->if_flags & IFF_UP) 4781590Srgrimes rt2661_init(sc); 4791590Srgrimes} 4801590Srgrimes 4811590Srgrimesstatic void 4821590Srgrimesrt2661_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error) 4831590Srgrimes{ 4841590Srgrimes if (error != 0) 4851590Srgrimes return; 4861590Srgrimes 4871590Srgrimes KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); 4881590Srgrimes 489138232Sharti *(bus_addr_t *)arg = segs[0].ds_addr; 4901590Srgrimes} 491143407Sharti 4921590Srgrimesstatic int 493143407Shartirt2661_alloc_tx_ring(struct rt2661_softc *sc, struct rt2661_tx_ring *ring, 4941590Srgrimes int count) 4951590Srgrimes{ 4961590Srgrimes int i, error; 4971590Srgrimes 4981590Srgrimes ring->count = count; 4991590Srgrimes ring->queued = 0; 5001590Srgrimes ring->cur = ring->next = ring->stat = 0; 5011590Srgrimes 5021590Srgrimes error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 4, 0, 5031590Srgrimes BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 5041590Srgrimes count * RT2661_TX_DESC_SIZE, 1, count * RT2661_TX_DESC_SIZE, 5051590Srgrimes 0, NULL, NULL, &ring->desc_dmat); 5061590Srgrimes if (error != 0) { 5071590Srgrimes device_printf(sc->sc_dev, "could not create desc DMA tag\n"); 5081590Srgrimes goto fail; 5091590Srgrimes } 5101590Srgrimes 511138232Sharti error = bus_dmamem_alloc(ring->desc_dmat, (void **)&ring->desc, 5121590Srgrimes BUS_DMA_NOWAIT | BUS_DMA_ZERO, &ring->desc_map); 513143407Sharti if (error != 0) { 514143407Sharti device_printf(sc->sc_dev, "could not allocate DMA memory\n"); 515143407Sharti goto fail; 5161590Srgrimes } 517187475Srdivacky 518143911Sharti error = bus_dmamap_load(ring->desc_dmat, ring->desc_map, ring->desc, 519143911Sharti count * RT2661_TX_DESC_SIZE, rt2661_dma_map_addr, &ring->physaddr, 520143407Sharti 0); 521143407Sharti if (error != 0) { 522143407Sharti device_printf(sc->sc_dev, "could not load desc DMA map\n"); 523143407Sharti goto fail; 524143407Sharti } 525143407Sharti 526143407Sharti ring->data = malloc(count * sizeof (struct rt2661_tx_data), M_DEVBUF, 527143407Sharti M_NOWAIT | M_ZERO); 528143407Sharti if (ring->data == NULL) { 529143407Sharti device_printf(sc->sc_dev, "could not allocate soft data\n"); 530143407Sharti error = ENOMEM; 531143407Sharti goto fail; 532143407Sharti } 533143407Sharti 534143407Sharti error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, 535143407Sharti BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 536143407Sharti RT2661_MAX_SCATTER, MCLBYTES, 0, NULL, NULL, &ring->data_dmat); 5371590Srgrimes if (error != 0) { 538143407Sharti device_printf(sc->sc_dev, "could not create data DMA tag\n"); 5391590Srgrimes goto fail; 540143407Sharti } 5411590Srgrimes 542143407Sharti for (i = 0; i < count; i++) { 543143407Sharti error = bus_dmamap_create(ring->data_dmat, 0, 544143407Sharti &ring->data[i].map); 545143407Sharti if (error != 0) { 546143407Sharti device_printf(sc->sc_dev, "could not create DMA map\n"); 547143407Sharti goto fail; 548143407Sharti } 5491590Srgrimes } 550143407Sharti 5511590Srgrimes return 0; 5521590Srgrimes 5531590Srgrimesfail: rt2661_free_tx_ring(sc, ring); 5541590Srgrimes return error; 5551590Srgrimes} 5561590Srgrimes 5571590Srgrimesstatic void 558143372Shartirt2661_reset_tx_ring(struct rt2661_softc *sc, struct rt2661_tx_ring *ring) 559143372Sharti{ 5601590Srgrimes struct rt2661_tx_desc *desc; 5611590Srgrimes struct rt2661_tx_data *data; 5621590Srgrimes int i; 5631590Srgrimes 5641590Srgrimes for (i = 0; i < ring->count; i++) { 5651590Srgrimes desc = &ring->desc[i]; 5661590Srgrimes data = &ring->data[i]; 567143372Sharti 568143372Sharti if (data->m != NULL) { 5691590Srgrimes bus_dmamap_sync(ring->data_dmat, data->map, 570143372Sharti BUS_DMASYNC_POSTWRITE); 5718874Srgrimes bus_dmamap_unload(ring->data_dmat, data->map); 572143372Sharti m_freem(data->m); 573143372Sharti data->m = NULL; 574143372Sharti } 575143372Sharti 5761590Srgrimes if (data->ni != NULL) { 577143372Sharti ieee80211_free_node(data->ni); 578143372Sharti data->ni = NULL; 579143372Sharti } 580143372Sharti 581143372Sharti desc->flags = 0; 582143372Sharti } 5831590Srgrimes 584143372Sharti bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_PREWRITE); 585143372Sharti 5861590Srgrimes ring->queued = 0; 587143372Sharti ring->cur = ring->next = ring->stat = 0; 588143372Sharti} 589143372Sharti 590143372Shartistatic void 591143372Shartirt2661_free_tx_ring(struct rt2661_softc *sc, struct rt2661_tx_ring *ring) 592143372Sharti{ 593143372Sharti struct rt2661_tx_data *data; 594143372Sharti int i; 595143372Sharti 5961590Srgrimes if (ring->desc != NULL) { 597143372Sharti bus_dmamap_sync(ring->desc_dmat, ring->desc_map, 598143372Sharti BUS_DMASYNC_POSTWRITE); 599143372Sharti bus_dmamap_unload(ring->desc_dmat, ring->desc_map); 600143372Sharti bus_dmamem_free(ring->desc_dmat, ring->desc, ring->desc_map); 6011590Srgrimes } 6021590Srgrimes 6031590Srgrimes if (ring->desc_dmat != NULL) 6041590Srgrimes bus_dma_tag_destroy(ring->desc_dmat); 6051590Srgrimes 606143556Sharti if (ring->data != NULL) { 6071590Srgrimes for (i = 0; i < ring->count; i++) { 6081590Srgrimes data = &ring->data[i]; 6091590Srgrimes 6101590Srgrimes if (data->m != NULL) { 6111590Srgrimes bus_dmamap_sync(ring->data_dmat, data->map, 6121590Srgrimes BUS_DMASYNC_POSTWRITE); 6131590Srgrimes bus_dmamap_unload(ring->data_dmat, data->map); 6141590Srgrimes m_freem(data->m); 6151590Srgrimes } 6161590Srgrimes 6171590Srgrimes if (data->ni != NULL) 6181590Srgrimes ieee80211_free_node(data->ni); 619143556Sharti 620143556Sharti if (data->map != NULL) 6211590Srgrimes bus_dmamap_destroy(ring->data_dmat, data->map); 622143407Sharti } 623143407Sharti 6241590Srgrimes free(ring->data, M_DEVBUF); 625143407Sharti } 626143407Sharti 627143407Sharti if (ring->data_dmat != NULL) 628143911Sharti bus_dma_tag_destroy(ring->data_dmat); 629143911Sharti} 630143911Sharti 631143407Shartistatic int 632143407Shartirt2661_alloc_rx_ring(struct rt2661_softc *sc, struct rt2661_rx_ring *ring, 633143911Sharti int count) 634143911Sharti{ 635143407Sharti struct rt2661_rx_desc *desc; 636143407Sharti struct rt2661_rx_data *data; 637143407Sharti bus_addr_t physaddr; 638143407Sharti int i, error; 639143407Sharti 640143407Sharti ring->count = count; 641143407Sharti ring->cur = ring->next = 0; 642143556Sharti 643143407Sharti error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 4, 0, 64473970Stmm BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 6451590Srgrimes count * RT2661_RX_DESC_SIZE, 1, count * RT2661_RX_DESC_SIZE, 6461590Srgrimes 0, NULL, NULL, &ring->desc_dmat); 647143807Sharti if (error != 0) { 648143807Sharti device_printf(sc->sc_dev, "could not create desc DMA tag\n"); 649143807Sharti goto fail; 650143407Sharti } 651143407Sharti 652143407Sharti error = bus_dmamem_alloc(ring->desc_dmat, (void **)&ring->desc, 653143407Sharti BUS_DMA_NOWAIT | BUS_DMA_ZERO, &ring->desc_map); 654143407Sharti if (error != 0) { 655143911Sharti device_printf(sc->sc_dev, "could not allocate DMA memory\n"); 656143911Sharti goto fail; 657143407Sharti } 658143407Sharti 659143407Sharti error = bus_dmamap_load(ring->desc_dmat, ring->desc_map, ring->desc, 660143407Sharti count * RT2661_RX_DESC_SIZE, rt2661_dma_map_addr, &ring->physaddr, 661143911Sharti 0); 662143407Sharti if (error != 0) { 663143407Sharti device_printf(sc->sc_dev, "could not load desc DMA map\n"); 664143407Sharti goto fail; 665143407Sharti } 666143407Sharti 667143407Sharti ring->data = malloc(count * sizeof (struct rt2661_rx_data), M_DEVBUF, 6681590Srgrimes M_NOWAIT | M_ZERO); 6691590Srgrimes if (ring->data == NULL) { 6701590Srgrimes device_printf(sc->sc_dev, "could not allocate soft data\n"); 6711590Srgrimes error = ENOMEM; 6721590Srgrimes goto fail; 6731590Srgrimes } 6741590Srgrimes 6751590Srgrimes /* 6761590Srgrimes * Pre-allocate Rx buffers and populate Rx ring. 6771590Srgrimes */ 6781590Srgrimes error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, 6791590Srgrimes BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 6801590Srgrimes 1, MCLBYTES, 0, NULL, NULL, &ring->data_dmat); 6811590Srgrimes if (error != 0) { 6821590Srgrimes device_printf(sc->sc_dev, "could not create data DMA tag\n"); 6831590Srgrimes goto fail; 6841590Srgrimes } 6851590Srgrimes 686138232Sharti for (i = 0; i < count; i++) { 6871590Srgrimes desc = &sc->rxq.desc[i]; 688143407Sharti data = &sc->rxq.data[i]; 689143407Sharti 6901590Srgrimes error = bus_dmamap_create(ring->data_dmat, 0, &data->map); 691143911Sharti if (error != 0) { 692143556Sharti device_printf(sc->sc_dev, "could not create DMA map\n"); 693143556Sharti goto fail; 694143556Sharti } 695143556Sharti 6961590Srgrimes data->m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 697143556Sharti if (data->m == NULL) { 6981590Srgrimes device_printf(sc->sc_dev, 699143556Sharti "could not allocate rx mbuf\n"); 700143556Sharti error = ENOMEM; 701144020Sharti goto fail; 702143556Sharti } 703143556Sharti 704143556Sharti error = bus_dmamap_load(ring->data_dmat, data->map, 705143556Sharti mtod(data->m, void *), MCLBYTES, rt2661_dma_map_addr, 706143556Sharti &physaddr, 0); 707143556Sharti if (error != 0) { 708138264Sharti device_printf(sc->sc_dev, 709143556Sharti "could not load rx buf DMA map"); 710143556Sharti goto fail; 711143556Sharti } 712143556Sharti 713143556Sharti desc->flags = htole32(RT2661_RX_BUSY); 714143556Sharti desc->physaddr = htole32(physaddr); 715143556Sharti } 716143556Sharti 7171590Srgrimes bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_PREWRITE); 7181590Srgrimes 7191590Srgrimes return 0; 7201590Srgrimes 7211590Srgrimesfail: rt2661_free_rx_ring(sc, ring); 7221590Srgrimes return error; 7231590Srgrimes} 7241590Srgrimes 72569527Swillstatic void 7261590Srgrimesrt2661_reset_rx_ring(struct rt2661_softc *sc, struct rt2661_rx_ring *ring) 7271590Srgrimes{ 7281590Srgrimes int i; 7291590Srgrimes 7301590Srgrimes for (i = 0; i < ring->count; i++) 7311590Srgrimes ring->desc[i].flags = htole32(RT2661_RX_BUSY); 732144020Sharti 733138232Sharti bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_PREWRITE); 7341590Srgrimes 735143407Sharti ring->cur = ring->next = 0; 7361590Srgrimes} 737143911Sharti 738143911Shartistatic void 739143407Shartirt2661_free_rx_ring(struct rt2661_softc *sc, struct rt2661_rx_ring *ring) 740143911Sharti{ 7411590Srgrimes struct rt2661_rx_data *data; 7421590Srgrimes int i; 7431590Srgrimes 7441590Srgrimes if (ring->desc != NULL) { 7451590Srgrimes bus_dmamap_sync(ring->desc_dmat, ring->desc_map, 7461590Srgrimes BUS_DMASYNC_POSTWRITE); 7471590Srgrimes bus_dmamap_unload(ring->desc_dmat, ring->desc_map); 7481590Srgrimes bus_dmamem_free(ring->desc_dmat, ring->desc, ring->desc_map); 7491590Srgrimes } 7501590Srgrimes 7511590Srgrimes if (ring->desc_dmat != NULL) 7521590Srgrimes bus_dma_tag_destroy(ring->desc_dmat); 7531590Srgrimes 7541590Srgrimes if (ring->data != NULL) { 7551590Srgrimes for (i = 0; i < ring->count; i++) { 75672645Sasmodai data = &ring->data[i]; 7571590Srgrimes 7581590Srgrimes if (data->m != NULL) { 7591590Srgrimes bus_dmamap_sync(ring->data_dmat, data->map, 7601590Srgrimes BUS_DMASYNC_POSTREAD); 7611590Srgrimes bus_dmamap_unload(ring->data_dmat, data->map); 762104696Sjmallett m_freem(data->m); 7631590Srgrimes } 764143407Sharti 765143407Sharti if (data->map != NULL) 766143407Sharti bus_dmamap_destroy(ring->data_dmat, data->map); 767144020Sharti } 768144020Sharti 7691590Srgrimes free(ring->data, M_DEVBUF); 770144020Sharti } 771144020Sharti 7721590Srgrimes if (ring->data_dmat != NULL) 773143407Sharti bus_dma_tag_destroy(ring->data_dmat); 774143407Sharti} 7751590Srgrimes 776144020Shartistatic struct ieee80211_node * 777144020Shartirt2661_node_alloc(struct ieee80211vap *vap, 778144020Sharti const uint8_t mac[IEEE80211_ADDR_LEN]) 7791590Srgrimes{ 7801590Srgrimes struct rt2661_node *rn; 781144020Sharti 782144020Sharti rn = malloc(sizeof (struct rt2661_node), M_80211_NODE, 783144020Sharti M_NOWAIT | M_ZERO); 7841590Srgrimes 785144020Sharti return (rn != NULL) ? &rn->ni : NULL; 7861590Srgrimes} 7871590Srgrimes 788144020Shartistatic void 789186558Sobrienrt2661_newassoc(struct ieee80211_node *ni, int isnew) 790143407Sharti{ 791144020Sharti struct ieee80211vap *vap = ni->ni_vap; 792144020Sharti 793186558Sobrien ieee80211_amrr_node_init(&RT2661_VAP(vap)->amrr, 794143407Sharti &RT2661_NODE(ni)->amrr, ni); 7951590Srgrimes} 796144020Sharti 797144020Shartistatic int 7981590Srgrimesrt2661_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) 7991590Srgrimes{ 8001590Srgrimes struct rt2661_vap *rvp = RT2661_VAP(vap); 8011590Srgrimes struct ieee80211com *ic = vap->iv_ic; 8021590Srgrimes struct rt2661_softc *sc = ic->ic_ifp->if_softc; 8031590Srgrimes int error; 8041590Srgrimes 8051590Srgrimes if (nstate == IEEE80211_S_INIT && vap->iv_state == IEEE80211_S_RUN) { 8061590Srgrimes uint32_t tmp; 8071590Srgrimes 8081590Srgrimes /* abort TSF synchronization */ 8091590Srgrimes tmp = RAL_READ(sc, RT2661_TXRX_CSR9); 8101590Srgrimes RAL_WRITE(sc, RT2661_TXRX_CSR9, tmp & ~0x00ffffff); 8111590Srgrimes } 8121590Srgrimes 8131590Srgrimes error = rvp->ral_newstate(vap, nstate, arg); 8141590Srgrimes 8151590Srgrimes if (error == 0 && nstate == IEEE80211_S_RUN) { 816138232Sharti struct ieee80211_node *ni = vap->iv_bss; 8171590Srgrimes 818143407Sharti if (vap->iv_opmode != IEEE80211_M_MONITOR) { 8191590Srgrimes rt2661_enable_mrr(sc); 820143911Sharti rt2661_set_txpreamble(sc); 821143407Sharti rt2661_set_basicrates(sc, &ni->ni_rates); 8221590Srgrimes rt2661_set_bssid(sc, ni->ni_bssid); 8231590Srgrimes } 8241590Srgrimes 8251590Srgrimes if (vap->iv_opmode == IEEE80211_M_HOSTAP || 8261590Srgrimes vap->iv_opmode == IEEE80211_M_IBSS) { 8271590Srgrimes error = rt2661_prepare_beacon(sc, vap); 8281590Srgrimes if (error != 0) 8291590Srgrimes return error; 8301590Srgrimes } 8311590Srgrimes if (vap->iv_opmode != IEEE80211_M_MONITOR) 8321590Srgrimes rt2661_enable_tsf_sync(sc); 8331590Srgrimes } 8341590Srgrimes return error; 8351590Srgrimes} 8361590Srgrimes 8371590Srgrimes/* 8381590Srgrimes * Read 16 bits at address 'addr' from the serial EEPROM (either 93C46 or 8391590Srgrimes * 93C66). 8401590Srgrimes */ 841138232Shartistatic uint16_t 8421590Srgrimesrt2661_eeprom_read(struct rt2661_softc *sc, uint8_t addr) 843143407Sharti{ 8441590Srgrimes uint32_t tmp; 845143911Sharti uint16_t val; 846143407Sharti int n; 8471590Srgrimes 8481590Srgrimes /* clock C once before the first command */ 849143567Sharti RT2661_EEPROM_CTL(sc, 0); 850143567Sharti 851143567Sharti RT2661_EEPROM_CTL(sc, RT2661_S); 852143567Sharti RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_C); 853143567Sharti RT2661_EEPROM_CTL(sc, RT2661_S); 854143567Sharti 855143567Sharti /* write start bit (1) */ 856143567Sharti RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_D); 857143567Sharti RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_D | RT2661_C); 858143567Sharti 859143567Sharti /* write READ opcode (10) */ 860143567Sharti RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_D); 861143567Sharti RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_D | RT2661_C); 862143567Sharti RT2661_EEPROM_CTL(sc, RT2661_S); 863143567Sharti RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_C); 864143567Sharti 865143567Sharti /* write address (A5-A0 or A7-A0) */ 866143567Sharti n = (RAL_READ(sc, RT2661_E2PROM_CSR) & RT2661_93C46) ? 5 : 7; 867143567Sharti for (; n >= 0; n--) { 868143567Sharti RT2661_EEPROM_CTL(sc, RT2661_S | 869143567Sharti (((addr >> n) & 1) << RT2661_SHIFT_D)); 870143567Sharti RT2661_EEPROM_CTL(sc, RT2661_S | 871143567Sharti (((addr >> n) & 1) << RT2661_SHIFT_D) | RT2661_C); 8721590Srgrimes } 8731590Srgrimes 8741590Srgrimes RT2661_EEPROM_CTL(sc, RT2661_S); 8751590Srgrimes 876143600Sharti /* read data Q15-Q0 */ 877143600Sharti val = 0; 8781590Srgrimes for (n = 15; n >= 0; n--) { 8791590Srgrimes RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_C); 8801590Srgrimes tmp = RAL_READ(sc, RT2661_E2PROM_CSR); 8811590Srgrimes val |= ((tmp & RT2661_Q) >> RT2661_SHIFT_Q) << n; 8821590Srgrimes RT2661_EEPROM_CTL(sc, RT2661_S); 883143600Sharti } 8841590Srgrimes 8851590Srgrimes RT2661_EEPROM_CTL(sc, 0); 886143600Sharti 8871590Srgrimes /* clear Chip Select and clock C */ 8881590Srgrimes RT2661_EEPROM_CTL(sc, RT2661_S); 889143600Sharti RT2661_EEPROM_CTL(sc, 0); 890143600Sharti RT2661_EEPROM_CTL(sc, RT2661_C); 8911590Srgrimes 892143600Sharti return val; 893143600Sharti} 894143600Sharti 895143556Shartistatic void 896143600Shartirt2661_tx_intr(struct rt2661_softc *sc) 897143556Sharti{ 8981590Srgrimes struct ifnet *ifp = sc->sc_ifp; 899143600Sharti struct rt2661_tx_ring *txq; 900143600Sharti struct rt2661_tx_data *data; 9018874Srgrimes struct rt2661_node *rn; 902143600Sharti uint32_t val; 903143600Sharti int qid, retrycnt; 904143600Sharti 905143600Sharti for (;;) { 906143600Sharti struct ieee80211_node *ni; 907143600Sharti struct mbuf *m; 908143600Sharti 909143600Sharti val = RAL_READ(sc, RT2661_STA_CSR4); 910143600Sharti if (!(val & RT2661_TX_STAT_VALID)) 911143600Sharti break; 912143600Sharti 913143600Sharti /* retrieve the queue in which this frame was sent */ 914143600Sharti qid = RT2661_TX_QID(val); 915143600Sharti txq = (qid <= 3) ? &sc->txq[qid] : &sc->mgtq; 916143600Sharti 917143600Sharti /* retrieve rate control algorithm context */ 918143600Sharti data = &txq->data[txq->stat]; 919143600Sharti m = data->m; 920143600Sharti data->m = NULL; 921143600Sharti ni = data->ni; 922143600Sharti data->ni = NULL; 923143600Sharti 924143407Sharti /* if no frame has been sent, ignore */ 925143600Sharti if (ni == NULL) 926143407Sharti continue; 927143407Sharti 928143600Sharti rn = RT2661_NODE(ni); 929143600Sharti 930143600Sharti switch (RT2661_TX_RESULT(val)) { 931143407Sharti case RT2661_TX_SUCCESS: 932143407Sharti retrycnt = RT2661_TX_RETRYCNT(val); 933143407Sharti 9341590Srgrimes DPRINTFN(sc, 10, "data frame sent successfully after " 9351590Srgrimes "%d retries\n", retrycnt); 9361590Srgrimes if (data->rix != IEEE80211_FIXED_RATE_NONE) 9371590Srgrimes ieee80211_amrr_tx_complete(&rn->amrr, 9385814Sjkh IEEE80211_AMRR_SUCCESS, retrycnt); 9395814Sjkh ifp->if_opackets++; 940138564Sharti break; 9411590Srgrimes 9421590Srgrimes case RT2661_TX_RETRY_FAIL: 943108470Sschweikh retrycnt = RT2661_TX_RETRYCNT(val); 9441590Srgrimes 9451590Srgrimes DPRINTFN(sc, 9, "%s\n", 9461590Srgrimes "sending data frame failed (too much retries)"); 9471590Srgrimes if (data->rix != IEEE80211_FIXED_RATE_NONE) 9481590Srgrimes ieee80211_amrr_tx_complete(&rn->amrr, 9495814Sjkh IEEE80211_AMRR_FAILURE, retrycnt); 950138512Sharti ifp->if_oerrors++; 9511590Srgrimes break; 952143407Sharti 953143407Sharti default: 954143407Sharti /* other failure */ 9555814Sjkh device_printf(sc->sc_dev, 9565814Sjkh "sending data frame failed 0x%08x\n", val); 957143407Sharti ifp->if_oerrors++; 958143556Sharti } 959143556Sharti 960143407Sharti DPRINTFN(sc, 15, "tx done q=%d idx=%u\n", qid, txq->stat); 9615814Sjkh 9625814Sjkh txq->queued--; 963143407Sharti if (++txq->stat >= txq->count) /* faster than % count */ 964143407Sharti txq->stat = 0; 9655814Sjkh 966143407Sharti if (m->m_flags & M_TXCB) 967143407Sharti ieee80211_process_callback(ni, m, 968143407Sharti RT2661_TX_RESULT(val) != RT2661_TX_SUCCESS); 969143407Sharti m_freem(m); 970143407Sharti ieee80211_free_node(ni); 971143407Sharti } 9725814Sjkh 973143407Sharti sc->sc_tx_timer = 0; 974143407Sharti ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 975143407Sharti 9765814Sjkh rt2661_start_locked(ifp); 977143407Sharti} 978143407Sharti 9795814Sjkhstatic void 980143407Shartirt2661_tx_dma_intr(struct rt2661_softc *sc, struct rt2661_tx_ring *txq) 981143407Sharti{ 9825814Sjkh struct rt2661_tx_desc *desc; 983143407Sharti struct rt2661_tx_data *data; 984143407Sharti 985143407Sharti bus_dmamap_sync(txq->desc_dmat, txq->desc_map, BUS_DMASYNC_POSTREAD); 986143407Sharti 987143407Sharti for (;;) { 9885814Sjkh desc = &txq->desc[txq->next]; 989143407Sharti data = &txq->data[txq->next]; 990143556Sharti 991143556Sharti if ((le32toh(desc->flags) & RT2661_TX_BUSY) || 992143407Sharti !(le32toh(desc->flags) & RT2661_TX_VALID)) 993143556Sharti break; 994143556Sharti 995143407Sharti bus_dmamap_sync(txq->data_dmat, data->map, 996143407Sharti BUS_DMASYNC_POSTWRITE); 997143407Sharti bus_dmamap_unload(txq->data_dmat, data->map); 9985814Sjkh 9995814Sjkh /* descriptor is no longer valid */ 1000143407Sharti desc->flags &= ~htole32(RT2661_TX_VALID); 10011590Srgrimes 10021590Srgrimes DPRINTFN(sc, 15, "tx dma done q=%p idx=%u\n", txq, txq->next); 10031590Srgrimes 10041590Srgrimes if (++txq->next >= txq->count) /* faster than % count */ 10051590Srgrimes txq->next = 0; 10061590Srgrimes } 10071590Srgrimes 10081590Srgrimes bus_dmamap_sync(txq->desc_dmat, txq->desc_map, BUS_DMASYNC_PREWRITE); 10091590Srgrimes} 10101590Srgrimes 10111590Srgrimesstatic void 10121590Srgrimesrt2661_rx_intr(struct rt2661_softc *sc) 10131590Srgrimes{ 10141590Srgrimes struct ifnet *ifp = sc->sc_ifp; 10151590Srgrimes struct ieee80211com *ic = ifp->if_l2com; 1016138512Sharti struct rt2661_rx_desc *desc; 10171590Srgrimes struct rt2661_rx_data *data; 1018143407Sharti bus_addr_t physaddr; 1019143407Sharti struct ieee80211_frame *wh; 1020143407Sharti struct ieee80211_node *ni; 10211590Srgrimes struct mbuf *mnew, *m; 1022143407Sharti int error; 10231590Srgrimes 1024143407Sharti bus_dmamap_sync(sc->rxq.desc_dmat, sc->rxq.desc_map, 1025143407Sharti BUS_DMASYNC_POSTREAD); 10261590Srgrimes 1027143407Sharti for (;;) { 10285814Sjkh int rssi; 1029143407Sharti 1030143407Sharti desc = &sc->rxq.desc[sc->rxq.cur]; 1031143407Sharti data = &sc->rxq.data[sc->rxq.cur]; 1032143407Sharti 1033143407Sharti if (le32toh(desc->flags) & RT2661_RX_BUSY) 10345814Sjkh break; 1035143407Sharti 10365814Sjkh if ((le32toh(desc->flags) & RT2661_RX_PHY_ERROR) || 1037143407Sharti (le32toh(desc->flags) & RT2661_RX_CRC_ERROR)) { 1038143407Sharti /* 1039143407Sharti * This should not happen since we did not request 10405814Sjkh * to receive those frames when we filled TXRX_CSR0. 1041144020Sharti */ 1042143407Sharti DPRINTFN(sc, 5, "PHY or CRC error flags 0x%08x\n", 1043143407Sharti le32toh(desc->flags)); 10445814Sjkh ifp->if_ierrors++; 1045143407Sharti goto skip; 10465814Sjkh } 1047143407Sharti 1048143407Sharti if ((le32toh(desc->flags) & RT2661_RX_CIPHER_MASK) != 0) { 1049143407Sharti ifp->if_ierrors++; 10505814Sjkh goto skip; 1051143407Sharti } 10525814Sjkh 1053143407Sharti /* 1054143407Sharti * Try to allocate a new mbuf for this ring element and load it 1055143407Sharti * before processing the current mbuf. If the ring element 10565814Sjkh * cannot be loaded, drop the received packet and reuse the old 1057143407Sharti * mbuf. In the unlikely case that the old mbuf can't be 1058143407Sharti * reloaded either, explicitly panic. 1059143407Sharti */ 1060143407Sharti mnew = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 10611590Srgrimes if (mnew == NULL) { 10621590Srgrimes ifp->if_ierrors++; 10631590Srgrimes goto skip; 10641590Srgrimes } 10651590Srgrimes 10661590Srgrimes bus_dmamap_sync(sc->rxq.data_dmat, data->map, 10671590Srgrimes BUS_DMASYNC_POSTREAD); 10681590Srgrimes bus_dmamap_unload(sc->rxq.data_dmat, data->map); 10691590Srgrimes 10701590Srgrimes error = bus_dmamap_load(sc->rxq.data_dmat, data->map, 107169527Swill mtod(mnew, void *), MCLBYTES, rt2661_dma_map_addr, 10721590Srgrimes &physaddr, 0); 10731590Srgrimes if (error != 0) { 10741590Srgrimes m_freem(mnew); 10751590Srgrimes 10761590Srgrimes /* try to reload the old mbuf */ 10771590Srgrimes error = bus_dmamap_load(sc->rxq.data_dmat, data->map, 10781590Srgrimes mtod(data->m, void *), MCLBYTES, 1079141270Sharti rt2661_dma_map_addr, &physaddr, 0); 10801590Srgrimes if (error != 0) { 1081143407Sharti /* very unlikely that it will fail... */ 1082143407Sharti panic("%s: could not load old rx mbuf", 1083143407Sharti device_get_name(sc->sc_dev)); 1084143407Sharti } 1085143407Sharti ifp->if_ierrors++; 1086143407Sharti goto skip; 1087143407Sharti } 10881590Srgrimes 1089143407Sharti /* 1090143407Sharti * New mbuf successfully loaded, update Rx ring and continue 10911590Srgrimes * processing. 1092143407Sharti */ 1093143407Sharti m = data->m; 10941590Srgrimes data->m = mnew; 1095143407Sharti desc->physaddr = htole32(physaddr); 1096143407Sharti 1097143407Sharti /* finalize mbuf */ 1098143407Sharti m->m_pkthdr.rcvif = ifp; 1099143407Sharti m->m_pkthdr.len = m->m_len = 1100143407Sharti (le32toh(desc->flags) >> 16) & 0xfff; 1101143407Sharti 1102143407Sharti rssi = rt2661_get_rssi(sc, desc->rssi); 1103143407Sharti 1104143911Sharti if (bpf_peers_present(ifp->if_bpf)) { 1105143407Sharti struct rt2661_rx_radiotap_header *tap = &sc->sc_rxtap; 1106143911Sharti uint32_t tsf_lo, tsf_hi; 1107143911Sharti 1108143407Sharti /* get timestamp (low and high 32 bits) */ 1109143407Sharti tsf_hi = RAL_READ(sc, RT2661_TXRX_CSR13); 1110143407Sharti tsf_lo = RAL_READ(sc, RT2661_TXRX_CSR12); 1111143407Sharti 1112143407Sharti tap->wr_tsf = 1113143407Sharti htole64(((uint64_t)tsf_hi << 32) | tsf_lo); 1114143407Sharti tap->wr_flags = 0; 1115143407Sharti tap->wr_rate = ieee80211_plcp2rate(desc->rate, 1116143407Sharti (desc->flags & htole32(RT2661_RX_OFDM)) ? 1117143407Sharti IEEE80211_T_OFDM : IEEE80211_T_CCK); 1118143407Sharti tap->wr_antsignal = rssi < 0 ? 0 : rssi; 1119143407Sharti 1120143407Sharti bpf_mtap2(ifp->if_bpf, tap, sc->sc_rxtap_len, m); 1121143407Sharti } 1122143407Sharti sc->sc_flags |= RAL_INPUT_RUNNING; 1123143407Sharti RAL_UNLOCK(sc); 1124143407Sharti wh = mtod(m, struct ieee80211_frame *); 1125143407Sharti 1126143567Sharti /* send the frame to the 802.11 layer */ 1127143567Sharti ni = ieee80211_find_rxnode(ic, 1128143407Sharti (struct ieee80211_frame_min *)wh); 1129143407Sharti if (ni != NULL) { 11305814Sjkh /* Error happened during RSSI conversion. */ 1131143407Sharti if (rssi < 0) 1132143407Sharti rssi = -30; /* XXX ignored by net80211 */ 11335814Sjkh 1134143407Sharti (void) ieee80211_input(ni, m, rssi, 1135143407Sharti RT2661_NOISE_FLOOR, 0); 1136143407Sharti ieee80211_free_node(ni); 1137143407Sharti } else 1138143407Sharti (void) ieee80211_input_all(ic, m, rssi, 1139143407Sharti RT2661_NOISE_FLOOR, 0); 11401590Srgrimes 11411590Srgrimes RAL_LOCK(sc); 1142143407Sharti sc->sc_flags &= ~RAL_INPUT_RUNNING; 11431590Srgrimes 11441590Srgrimesskip: desc->flags |= htole32(RT2661_RX_BUSY); 11451590Srgrimes 1146143327Sharti DPRINTFN(sc, 15, "rx intr idx=%u\n", sc->rxq.cur); 1147143327Sharti 11481590Srgrimes sc->rxq.cur = (sc->rxq.cur + 1) % RT2661_RX_RING_COUNT; 1149143327Sharti } 1150143327Sharti 11511590Srgrimes bus_dmamap_sync(sc->rxq.desc_dmat, sc->rxq.desc_map, 1152143327Sharti BUS_DMASYNC_PREWRITE); 1153143327Sharti} 1154143327Sharti 11551590Srgrimes/* ARGSUSED */ 1156143327Shartistatic void 11578874Srgrimesrt2661_mcu_beacon_expire(struct rt2661_softc *sc) 1158143327Sharti{ 1159146027Sharti /* do nothing */ 1160143959Sharti} 1161143327Sharti 1162143327Shartistatic void 1163143327Shartirt2661_mcu_wakeup(struct rt2661_softc *sc) 1164143327Sharti{ 1165143327Sharti RAL_WRITE(sc, RT2661_MAC_CSR11, 5 << 16); 1166143327Sharti 1167143327Sharti RAL_WRITE(sc, RT2661_SOFT_RESET_CSR, 0x7); 1168143327Sharti RAL_WRITE(sc, RT2661_IO_CNTL_CSR, 0x18); 1169143327Sharti RAL_WRITE(sc, RT2661_PCI_USEC_CSR, 0x20); 1170143327Sharti 1171143327Sharti /* send wakeup command to MCU */ 1172143327Sharti rt2661_tx_cmd(sc, RT2661_MCU_CMD_WAKEUP, 0); 1173143297Sharti} 1174143327Sharti 1175143327Shartistatic void 1176143327Shartirt2661_mcu_cmd_intr(struct rt2661_softc *sc) 1177143327Sharti{ 1178143297Sharti RAL_READ(sc, RT2661_M2H_CMD_DONE_CSR); 1179143327Sharti RAL_WRITE(sc, RT2661_M2H_CMD_DONE_CSR, 0xffffffff); 1180143327Sharti} 1181143312Sharti 1182143327Shartivoid 1183143327Shartirt2661_intr(void *arg) 1184143327Sharti{ 1185143327Sharti struct rt2661_softc *sc = arg; 1186143327Sharti struct ifnet *ifp = sc->sc_ifp; 1187143327Sharti uint32_t r1, r2; 1188143327Sharti 1189143327Sharti RAL_LOCK(sc); 11901590Srgrimes 1191143327Sharti /* disable MAC and MCU interrupts */ 1192143327Sharti RAL_WRITE(sc, RT2661_INT_MASK_CSR, 0xffffff7f); 1193143327Sharti RAL_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0xffffffff); 1194143312Sharti 1195143327Sharti /* don't re-enable interrupts if we're shutting down */ 1196143327Sharti if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { 1197143327Sharti RAL_UNLOCK(sc); 1198143312Sharti return; 1199143327Sharti } 1200143327Sharti 1201143327Sharti r1 = RAL_READ(sc, RT2661_INT_SOURCE_CSR); 1202143312Sharti RAL_WRITE(sc, RT2661_INT_SOURCE_CSR, r1); 1203143327Sharti 1204143327Sharti r2 = RAL_READ(sc, RT2661_MCU_INT_SOURCE_CSR); 1205143312Sharti RAL_WRITE(sc, RT2661_MCU_INT_SOURCE_CSR, r2); 1206143327Sharti 1207143327Sharti if (r1 & RT2661_MGT_DONE) 1208143327Sharti rt2661_tx_dma_intr(sc, &sc->mgtq); 12091590Srgrimes 1210143327Sharti if (r1 & RT2661_RX_DONE) 1211143327Sharti rt2661_rx_intr(sc); 1212143327Sharti 1213143312Sharti if (r1 & RT2661_TX0_DMA_DONE) 1214143327Sharti rt2661_tx_dma_intr(sc, &sc->txq[0]); 1215143327Sharti 1216143327Sharti if (r1 & RT2661_TX1_DMA_DONE) 1217143312Sharti rt2661_tx_dma_intr(sc, &sc->txq[1]); 1218143327Sharti 1219143327Sharti if (r1 & RT2661_TX2_DMA_DONE) 1220143327Sharti rt2661_tx_dma_intr(sc, &sc->txq[2]); 1221143327Sharti 1222143327Sharti if (r1 & RT2661_TX3_DMA_DONE) 1223143312Sharti rt2661_tx_dma_intr(sc, &sc->txq[3]); 1224143327Sharti 12251590Srgrimes if (r1 & RT2661_TX_DONE) 1226143327Sharti rt2661_tx_intr(sc); 1227143312Sharti 1228143327Sharti if (r2 & RT2661_MCU_CMD_DONE) 1229143327Sharti rt2661_mcu_cmd_intr(sc); 1230143312Sharti 1231143327Sharti if (r2 & RT2661_MCU_BEACON_EXPIRE) 1232143327Sharti rt2661_mcu_beacon_expire(sc); 1233143312Sharti 1234143327Sharti if (r2 & RT2661_MCU_WAKEUP) 1235143327Sharti rt2661_mcu_wakeup(sc); 1236143327Sharti 1237143327Sharti /* re-enable MAC and MCU interrupts */ 1238143327Sharti RAL_WRITE(sc, RT2661_INT_MASK_CSR, 0x0000ff10); 1239143327Sharti RAL_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0); 1240143327Sharti 1241143327Sharti RAL_UNLOCK(sc); 1242143327Sharti} 1243143327Sharti 1244143327Shartistatic uint8_t 1245143327Shartirt2661_plcp_signal(int rate) 1246143327Sharti{ 1247144020Sharti switch (rate) { 1248143327Sharti /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */ 1249143327Sharti case 12: return 0xb; 1250143327Sharti case 18: return 0xf; 1251143327Sharti case 24: return 0xa; 1252143327Sharti case 36: return 0xe; 1253143327Sharti case 48: return 0x9; 1254143327Sharti case 72: return 0xd; 1255143327Sharti case 96: return 0x8; 1256143327Sharti case 108: return 0xc; 1257143327Sharti 1258143327Sharti /* CCK rates (NB: not IEEE std, device-specific) */ 1259143807Sharti case 2: return 0x0; 1260143807Sharti case 4: return 0x1; 1261143807Sharti case 11: return 0x2; 1262143807Sharti case 22: return 0x3; 1263143327Sharti } 1264143327Sharti return 0xff; /* XXX unsupported/unknown rate */ 1265143327Sharti} 1266143327Sharti 1267143327Shartistatic void 1268143327Shartirt2661_setup_tx_desc(struct rt2661_softc *sc, struct rt2661_tx_desc *desc, 1269143327Sharti uint32_t flags, uint16_t xflags, int len, int rate, 1270143327Sharti const bus_dma_segment_t *segs, int nsegs, int ac) 1271143327Sharti{ 1272143312Sharti struct ifnet *ifp = sc->sc_ifp; 1273143327Sharti struct ieee80211com *ic = ifp->if_l2com; 1274143312Sharti uint16_t plcp_length; 1275143327Sharti int i, remainder; 1276143327Sharti 1277143312Sharti desc->flags = htole32(flags); 1278143327Sharti desc->flags |= htole32(len << 16); 1279143327Sharti desc->flags |= htole32(RT2661_TX_BUSY | RT2661_TX_VALID); 1280143327Sharti 1281143327Sharti desc->xflags = htole16(xflags); 1282144020Sharti desc->xflags |= htole16(nsegs << 13); 12831590Srgrimes 1284143327Sharti desc->wme = htole16( 12851590Srgrimes RT2661_QID(ac) | 1286143327Sharti RT2661_AIFSN(2) | 12871590Srgrimes RT2661_LOGCWMIN(4) | 1288143327Sharti RT2661_LOGCWMAX(10)); 12891590Srgrimes 1290143327Sharti /* 1291143327Sharti * Remember in which queue this frame was sent. This field is driver 1292143327Sharti * private data only. It will be made available by the NIC in STA_CSR4 1293143327Sharti * on Tx interrupts. 1294138916Sharti */ 1295143327Sharti desc->qid = ac; 1296143327Sharti 1297143327Sharti /* setup PLCP fields */ 1298143327Sharti desc->plcp_signal = rt2661_plcp_signal(rate); 1299143327Sharti desc->plcp_service = 4; 1300143327Sharti 1301143327Sharti len += IEEE80211_CRC_LEN; 1302143327Sharti if (ieee80211_rate2phytype(ic->ic_rt, rate) == IEEE80211_T_OFDM) { 1303143327Sharti desc->flags |= htole32(RT2661_TX_OFDM); 1304143327Sharti 1305143327Sharti plcp_length = len & 0xfff; 1306143327Sharti desc->plcp_length_hi = plcp_length >> 6; 1307143327Sharti desc->plcp_length_lo = plcp_length & 0x3f; 1308143327Sharti } else { 1309143327Sharti plcp_length = (16 * len + rate - 1) / rate; 1310143327Sharti if (rate == 22) { 1311143327Sharti remainder = (16 * len) % 22; 1312143327Sharti if (remainder != 0 && remainder < 7) 1313143327Sharti desc->plcp_service |= RT2661_PLCP_LENGEXT; 1314143327Sharti } 1315143327Sharti desc->plcp_length_hi = plcp_length >> 8; 1316143327Sharti desc->plcp_length_lo = plcp_length & 0xff; 1317143327Sharti 1318143327Sharti if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) 1319143327Sharti desc->plcp_signal |= 0x08; 1320143327Sharti } 1321143327Sharti 1322143327Sharti /* RT2x61 supports scatter with up to 5 segments */ 1323143327Sharti for (i = 0; i < nsegs; i++) { 1324143327Sharti desc->addr[i] = htole32(segs[i].ds_addr); 1325143327Sharti desc->len [i] = htole16(segs[i].ds_len); 1326143327Sharti } 1327143297Sharti} 1328143327Sharti 1329143327Shartistatic int 1330143327Shartirt2661_tx_mgt(struct rt2661_softc *sc, struct mbuf *m0, 1331143327Sharti struct ieee80211_node *ni) 1332143297Sharti{ 1333143327Sharti struct ieee80211vap *vap = ni->ni_vap; 1334143327Sharti struct ieee80211com *ic = ni->ni_ic; 1335143297Sharti struct ifnet *ifp = sc->sc_ifp; 1336143327Sharti struct rt2661_tx_desc *desc; 1337143327Sharti struct rt2661_tx_data *data; 13381590Srgrimes struct ieee80211_frame *wh; 1339143327Sharti struct ieee80211_key *k; 1340143327Sharti bus_dma_segment_t segs[RT2661_MAX_SCATTER]; 13411590Srgrimes uint16_t dur; 1342143297Sharti uint32_t flags = 0; /* XXX HWSEQ */ 1343143327Sharti int nsegs, rate, error; 1344143327Sharti 1345143327Sharti desc = &sc->mgtq.desc[sc->mgtq.cur]; 1346143297Sharti data = &sc->mgtq.data[sc->mgtq.cur]; 13471590Srgrimes 1348143297Sharti rate = vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)].mgmtrate; 1349143327Sharti 1350143327Sharti wh = mtod(m0, struct ieee80211_frame *); 1351143297Sharti 1352143327Sharti if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 13531590Srgrimes k = ieee80211_crypto_encap(ni, m0); 1354143327Sharti if (k == NULL) { 1355143327Sharti m_freem(m0); 1356143327Sharti return ENOBUFS; 1357143327Sharti } 1358143327Sharti } 1359143327Sharti 13601590Srgrimes error = bus_dmamap_load_mbuf_sg(sc->mgtq.data_dmat, data->map, m0, 1361143327Sharti segs, &nsegs, 0); 1362143327Sharti if (error != 0) { 1363143327Sharti device_printf(sc->sc_dev, "could not map mbuf (error %d)\n", 1364143327Sharti error); 1365143327Sharti m_freem(m0); 1366143327Sharti return error; 1367143297Sharti } 1368143297Sharti 13691590Srgrimes if (bpf_peers_present(ifp->if_bpf)) { 1370143297Sharti struct rt2661_tx_radiotap_header *tap = &sc->sc_txtap; 1371143327Sharti 1372143327Sharti tap->wt_flags = 0; 1373143327Sharti tap->wt_rate = rate; 1374143297Sharti 1375143327Sharti bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m0); 1376143327Sharti } 1377143327Sharti 1378143327Sharti data->m = m0; 1379143327Sharti data->ni = ni; 1380143297Sharti /* management frames are not taken into account for amrr */ 13811590Srgrimes data->rix = IEEE80211_FIXED_RATE_NONE; 13821590Srgrimes 13831590Srgrimes wh = mtod(m0, struct ieee80211_frame *); 13841590Srgrimes 13851590Srgrimes if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { 13861590Srgrimes flags |= RT2661_TX_NEED_ACK; 13871590Srgrimes 13881590Srgrimes dur = ieee80211_ack_duration(ic->ic_rt, 13891590Srgrimes rate, ic->ic_flags & IEEE80211_F_SHPREAMBLE); 13901590Srgrimes *(uint16_t *)wh->i_dur = htole16(dur); 13911590Srgrimes 13921590Srgrimes /* tell hardware to add timestamp in probe responses */ 13931590Srgrimes if ((wh->i_fc[0] & 13941590Srgrimes (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == 13951590Srgrimes (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP)) 13961590Srgrimes flags |= RT2661_TX_TIMESTAMP; 13971590Srgrimes } 13981590Srgrimes 13991590Srgrimes rt2661_setup_tx_desc(sc, desc, flags, 0 /* XXX HWSEQ */, 14001590Srgrimes m0->m_pkthdr.len, rate, segs, nsegs, RT2661_QID_MGT); 14011590Srgrimes 14021590Srgrimes bus_dmamap_sync(sc->mgtq.data_dmat, data->map, BUS_DMASYNC_PREWRITE); 1403104696Sjmallett bus_dmamap_sync(sc->mgtq.desc_dmat, sc->mgtq.desc_map, 14041590Srgrimes BUS_DMASYNC_PREWRITE); 1405143407Sharti 1406143407Sharti DPRINTFN(sc, 10, "sending mgt frame len=%u idx=%u rate=%u\n", 1407143407Sharti m0->m_pkthdr.len, sc->mgtq.cur, rate); 14081590Srgrimes 1409143407Sharti /* kick mgt */ 14101590Srgrimes sc->mgtq.queued++; 14111590Srgrimes sc->mgtq.cur = (sc->mgtq.cur + 1) % RT2661_MGT_RING_COUNT; 14121590Srgrimes RAL_WRITE(sc, RT2661_TX_CNTL_CSR, RT2661_KICK_MGT); 14131590Srgrimes 1414143407Sharti return 0; 1415143407Sharti} 14161590Srgrimes 14171590Srgrimesstatic int 14181590Srgrimesrt2661_sendprot(struct rt2661_softc *sc, int ac, 1419143407Sharti const struct mbuf *m, struct ieee80211_node *ni, int prot, int rate) 1420143407Sharti{ 1421143407Sharti struct ieee80211com *ic = ni->ni_ic; 1422143407Sharti struct rt2661_tx_ring *txq = &sc->txq[ac]; 1423143407Sharti const struct ieee80211_frame *wh; 1424143407Sharti struct rt2661_tx_desc *desc; 1425143407Sharti struct rt2661_tx_data *data; 1426143407Sharti struct mbuf *mprot; 1427143407Sharti int protrate, ackrate, pktlen, flags, isshort, error; 1428143407Sharti uint16_t dur; 1429143407Sharti bus_dma_segment_t segs[RT2661_MAX_SCATTER]; 1430143407Sharti int nsegs; 1431143407Sharti 1432143407Sharti KASSERT(prot == IEEE80211_PROT_RTSCTS || prot == IEEE80211_PROT_CTSONLY, 1433143407Sharti ("protection %d", prot)); 1434143407Sharti 1435143407Sharti wh = mtod(m, const struct ieee80211_frame *); 1436143407Sharti pktlen = m->m_pkthdr.len + IEEE80211_CRC_LEN; 1437143407Sharti 1438143407Sharti protrate = ieee80211_ctl_rate(ic->ic_rt, rate); 1439143407Sharti ackrate = ieee80211_ack_rate(ic->ic_rt, rate); 1440143407Sharti 1441143407Sharti isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0; 14421590Srgrimes dur = ieee80211_compute_duration(ic->ic_rt, pktlen, rate, isshort) 1443143407Sharti + ieee80211_ack_duration(ic->ic_rt, rate, isshort); 14441590Srgrimes flags = RT2661_TX_MORE_FRAG; 1445143407Sharti if (prot == IEEE80211_PROT_RTSCTS) { 1446143911Sharti /* NB: CTS is the same size as an ACK */ 1447143407Sharti dur += ieee80211_ack_duration(ic->ic_rt, rate, isshort); 14481590Srgrimes flags |= RT2661_TX_NEED_ACK; 1449143911Sharti mprot = ieee80211_alloc_rts(ic, wh->i_addr1, wh->i_addr2, dur); 1450143407Sharti } else { 1451143407Sharti mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, dur); 1452143407Sharti } 1453143407Sharti if (mprot == NULL) { 1454143407Sharti /* XXX stat + msg */ 1455143407Sharti return ENOBUFS; 1456143407Sharti } 14578874Srgrimes 1458143407Sharti data = &txq->data[txq->cur]; 1459143407Sharti desc = &txq->desc[txq->cur]; 14608874Srgrimes 1461143407Sharti error = bus_dmamap_load_mbuf_sg(txq->data_dmat, data->map, mprot, segs, 1462143407Sharti &nsegs, 0); 1463143407Sharti if (error != 0) { 1464143407Sharti device_printf(sc->sc_dev, 14651590Srgrimes "could not map mbuf (error %d)\n", error); 1466143407Sharti m_freem(mprot); 1467143407Sharti return error; 1468143407Sharti } 1469143407Sharti 14701590Srgrimes data->m = mprot; 1471143407Sharti data->ni = ieee80211_ref_node(ni); 1472143407Sharti /* ctl frames are not taken into account for amrr */ 1473143407Sharti data->rix = IEEE80211_FIXED_RATE_NONE; 1474143407Sharti 1475143407Sharti rt2661_setup_tx_desc(sc, desc, flags, 0, mprot->m_pkthdr.len, 1476143407Sharti protrate, segs, 1, ac); 1477143407Sharti 14781590Srgrimes bus_dmamap_sync(txq->data_dmat, data->map, BUS_DMASYNC_PREWRITE); 1479143407Sharti bus_dmamap_sync(txq->desc_dmat, txq->desc_map, BUS_DMASYNC_PREWRITE); 1480143407Sharti 1481143407Sharti txq->queued++; 1482143407Sharti txq->cur = (txq->cur + 1) % RT2661_TX_RING_COUNT; 1483143407Sharti 1484143407Sharti return 0; 1485143407Sharti} 14861590Srgrimes 14871590Srgrimesstatic int 14881590Srgrimesrt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m0, 14891590Srgrimes struct ieee80211_node *ni, int ac) 14901590Srgrimes{ 14911590Srgrimes struct ieee80211vap *vap = ni->ni_vap; 14921590Srgrimes struct ifnet *ifp = sc->sc_ifp; 14931590Srgrimes struct ieee80211com *ic = ifp->if_l2com; 14941590Srgrimes struct rt2661_tx_ring *txq = &sc->txq[ac]; 14951590Srgrimes struct rt2661_tx_desc *desc; 14961590Srgrimes struct rt2661_tx_data *data; 14971590Srgrimes struct ieee80211_frame *wh; 14981590Srgrimes const struct ieee80211_txparam *tp; 14991590Srgrimes struct ieee80211_key *k; 15001590Srgrimes const struct chanAccParams *cap; 15011590Srgrimes struct mbuf *mnew; 15021590Srgrimes bus_dma_segment_t segs[RT2661_MAX_SCATTER]; 1503138512Sharti uint16_t dur; 15041590Srgrimes uint32_t flags; 1505143407Sharti int error, nsegs, rate, noack = 0; 1506143407Sharti 1507146149Sharti wh = mtod(m0, struct ieee80211_frame *); 1508143407Sharti 1509146149Sharti tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)]; 1510146149Sharti if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { 1511146149Sharti rate = tp->mcastrate; 1512143407Sharti } else if (m0->m_flags & M_EAPOL) { 1513143407Sharti rate = tp->mgmtrate; 1514143407Sharti } else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { 15158874Srgrimes rate = tp->ucastrate; 1516143407Sharti } else { 1517143407Sharti (void) ieee80211_amrr_choose(ni, &RT2661_NODE(ni)->amrr); 1518143407Sharti rate = ni->ni_txrate; 1519143407Sharti } 1520143407Sharti rate &= IEEE80211_RATE_VAL; 1521143407Sharti 15221590Srgrimes if (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_QOS) { 1523143407Sharti cap = &ic->ic_wme.wme_chanParams; 1524143407Sharti noack = cap->cap_wmeParams[ac].wmep_noackPolicy; 15251590Srgrimes } 1526143407Sharti 15278874Srgrimes if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 1528143407Sharti k = ieee80211_crypto_encap(ni, m0); 1529143407Sharti if (k == NULL) { 1530143407Sharti m_freem(m0); 1531143407Sharti return ENOBUFS; 1532143407Sharti } 1533143407Sharti 1534143407Sharti /* packet header may have moved, reset our local pointer */ 1535143407Sharti wh = mtod(m0, struct ieee80211_frame *); 1536143407Sharti } 15371590Srgrimes 1538143407Sharti flags = 0; 1539143407Sharti if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { 1540143407Sharti int prot = IEEE80211_PROT_NONE; 1541143407Sharti if (m0->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold) 1542143407Sharti prot = IEEE80211_PROT_RTSCTS; 1543143407Sharti else if ((ic->ic_flags & IEEE80211_F_USEPROT) && 1544143407Sharti ieee80211_rate2phytype(ic->ic_rt, rate) == IEEE80211_T_OFDM) 1545143407Sharti prot = ic->ic_protmode; 15468874Srgrimes if (prot != IEEE80211_PROT_NONE) { 1547143407Sharti error = rt2661_sendprot(sc, ac, m0, ni, prot, rate); 1548143407Sharti if (error) { 1549143407Sharti m_freem(m0); 1550146580Sharti return error; 1551146580Sharti } 15525814Sjkh flags |= RT2661_TX_LONG_RETRY | RT2661_TX_IFS; 1553143407Sharti } 1554143407Sharti } 1555143407Sharti 1556143407Sharti data = &txq->data[txq->cur]; 1557143407Sharti desc = &txq->desc[txq->cur]; 1558143407Sharti 1559143407Sharti error = bus_dmamap_load_mbuf_sg(txq->data_dmat, data->map, m0, segs, 1560143407Sharti &nsegs, 0); 1561143407Sharti if (error != 0 && error != EFBIG) { 15621590Srgrimes device_printf(sc->sc_dev, "could not map mbuf (error %d)\n", 15631590Srgrimes error); 1564143407Sharti m_freem(m0); 1565143407Sharti return error; 1566143407Sharti } 1567143407Sharti if (error != 0) { 15681590Srgrimes mnew = m_defrag(m0, M_DONTWAIT); 1569143407Sharti if (mnew == NULL) { 1570143407Sharti device_printf(sc->sc_dev, 1571143407Sharti "could not defragment mbuf\n"); 1572143407Sharti m_freem(m0); 1573143407Sharti return ENOBUFS; 1574143407Sharti } 1575143407Sharti m0 = mnew; 1576143407Sharti 15771590Srgrimes error = bus_dmamap_load_mbuf_sg(txq->data_dmat, data->map, m0, 1578143407Sharti segs, &nsegs, 0); 1579143407Sharti if (error != 0) { 1580143407Sharti device_printf(sc->sc_dev, 1581143807Sharti "could not map mbuf (error %d)\n", error); 1582143807Sharti m_freem(m0); 1583143807Sharti return error; 1584143807Sharti } 15851590Srgrimes 1586143407Sharti /* packet header have moved, reset our local pointer */ 1587143407Sharti wh = mtod(m0, struct ieee80211_frame *); 1588143407Sharti } 1589143407Sharti 1590143407Sharti if (bpf_peers_present(ifp->if_bpf)) { 1591143407Sharti struct rt2661_tx_radiotap_header *tap = &sc->sc_txtap; 1592143407Sharti 1593143407Sharti tap->wt_flags = 0; 1594143407Sharti tap->wt_rate = rate; 1595143407Sharti tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); 1596143407Sharti tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); 1597143407Sharti 15981590Srgrimes bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m0); 1599143407Sharti } 1600143407Sharti 16011590Srgrimes data->m = m0; 1602143407Sharti data->ni = ni; 1603143407Sharti 16041590Srgrimes /* remember link conditions for rate adaptation algorithm */ 16051590Srgrimes if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE) { 1606143407Sharti data->rix = ni->ni_txrate; 1607143407Sharti /* XXX probably need last rssi value and not avg */ 1608143407Sharti data->rssi = ic->ic_node_getrssi(ni); 16091590Srgrimes } else 1610143407Sharti data->rix = IEEE80211_FIXED_RATE_NONE; 1611143407Sharti 16121590Srgrimes if (!noack && !IEEE80211_IS_MULTICAST(wh->i_addr1)) { 16131590Srgrimes flags |= RT2661_TX_NEED_ACK; 1614143407Sharti 1615143407Sharti dur = ieee80211_ack_duration(ic->ic_rt, 1616143407Sharti rate, ic->ic_flags & IEEE80211_F_SHPREAMBLE); 1617143407Sharti *(uint16_t *)wh->i_dur = htole16(dur); 1618143407Sharti } 16191590Srgrimes 16201590Srgrimes rt2661_setup_tx_desc(sc, desc, flags, 0, m0->m_pkthdr.len, rate, segs, 16211590Srgrimes nsegs, ac); 16221590Srgrimes 16231590Srgrimes bus_dmamap_sync(txq->data_dmat, data->map, BUS_DMASYNC_PREWRITE); 16241590Srgrimes bus_dmamap_sync(txq->desc_dmat, txq->desc_map, BUS_DMASYNC_PREWRITE); 16251590Srgrimes 16261590Srgrimes DPRINTFN(sc, 10, "sending data frame len=%u idx=%u rate=%u\n", 16271590Srgrimes m0->m_pkthdr.len, txq->cur, rate); 16281590Srgrimes 16291590Srgrimes /* kick Tx */ 16301590Srgrimes txq->queued++; 16311590Srgrimes txq->cur = (txq->cur + 1) % RT2661_TX_RING_COUNT; 16321590Srgrimes RAL_WRITE(sc, RT2661_TX_CNTL_CSR, 1 << ac); 16331590Srgrimes 16341590Srgrimes return 0; 1635138512Sharti} 16361590Srgrimes 1637143407Shartistatic void 1638143407Shartirt2661_start_locked(struct ifnet *ifp) 1639143407Sharti{ 1640143407Sharti struct rt2661_softc *sc = ifp->if_softc; 1641143407Sharti struct mbuf *m; 1642143407Sharti struct ieee80211_node *ni; 1643143407Sharti int ac; 1644143407Sharti 1645143407Sharti RAL_LOCK_ASSERT(sc); 1646143407Sharti 1647143407Sharti /* prevent management frames from being sent if we're not ready */ 16481590Srgrimes if (!(ifp->if_drv_flags & IFF_DRV_RUNNING) || sc->sc_invalid) 1649143407Sharti return; 1650143407Sharti 16511590Srgrimes for (;;) { 1652143407Sharti IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 1653143407Sharti if (m == NULL) 1654143407Sharti break; 1655143407Sharti 1656143407Sharti ac = M_WME_GETAC(m); 1657143407Sharti if (sc->txq[ac].queued >= RT2661_TX_RING_COUNT - 1) { 16581590Srgrimes /* there is no place left in this ring */ 16591590Srgrimes IFQ_DRV_PREPEND(&ifp->if_snd, m); 1660143407Sharti ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1661143407Sharti break; 1662143407Sharti } 1663143407Sharti 1664143407Sharti ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; 1665143407Sharti m = ieee80211_encap(ni, m); 1666143407Sharti if (m == NULL) { 1667143407Sharti ieee80211_free_node(ni); 1668143407Sharti ifp->if_oerrors++; 1669143407Sharti continue; 1670143407Sharti } 1671143407Sharti 1672143407Sharti if (rt2661_tx_data(sc, m, ni, ac) != 0) { 1673143407Sharti ieee80211_free_node(ni); 1674143407Sharti ifp->if_oerrors++; 1675143407Sharti break; 16761590Srgrimes } 16771590Srgrimes 1678143407Sharti sc->sc_tx_timer = 5; 1679143407Sharti } 1680143407Sharti} 1681143407Sharti 1682143807Shartistatic void 1683143807Shartirt2661_start(struct ifnet *ifp) 1684143807Sharti{ 1685143807Sharti struct rt2661_softc *sc = ifp->if_softc; 1686143807Sharti 1687143807Sharti RAL_LOCK(sc); 1688143407Sharti rt2661_start_locked(ifp); 1689143407Sharti RAL_UNLOCK(sc); 1690143407Sharti} 1691143407Sharti 1692143407Shartistatic int 1693143407Shartirt2661_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, 1694143407Sharti const struct ieee80211_bpf_params *params) 1695143407Sharti{ 1696143567Sharti struct ieee80211com *ic = ni->ni_ic; 1697143567Sharti struct ifnet *ifp = ic->ic_ifp; 1698143407Sharti struct rt2661_softc *sc = ifp->if_softc; 16998874Srgrimes 1700143407Sharti RAL_LOCK(sc); 1701143407Sharti 1702143407Sharti /* prevent management frames from being sent if we're not ready */ 1703143407Sharti if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { 1704143407Sharti RAL_UNLOCK(sc); 1705143407Sharti m_freem(m); 1706143807Sharti ieee80211_free_node(ni); 1707143407Sharti return ENETDOWN; 1708143407Sharti } 1709143407Sharti if (sc->mgtq.queued >= RT2661_MGT_RING_COUNT) { 17101590Srgrimes ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1711143407Sharti RAL_UNLOCK(sc); 1712143407Sharti m_freem(m); 1713143407Sharti ieee80211_free_node(ni); 1714143407Sharti return ENOBUFS; /* XXX */ 17151590Srgrimes } 1716143407Sharti 1717143407Sharti ifp->if_opackets++; 1718143407Sharti 1719143407Sharti /* 17201590Srgrimes * Legacy path; interpret frame contents to decide 1721143407Sharti * precisely how to send the frame. 1722143407Sharti * XXX raw path 1723143407Sharti */ 1724143407Sharti if (rt2661_tx_mgt(sc, m, ni) != 0) 1725143407Sharti goto bad; 17261590Srgrimes sc->sc_tx_timer = 5; 17271590Srgrimes 1728143407Sharti RAL_UNLOCK(sc); 1729143407Sharti 1730143407Sharti return 0; 1731143407Shartibad: 1732143407Sharti ifp->if_oerrors++; 1733143407Sharti ieee80211_free_node(ni); 17348874Srgrimes RAL_UNLOCK(sc); 1735143567Sharti return EIO; /* XXX */ 1736143567Sharti} 1737143407Sharti 17381590Srgrimesstatic void 1739143407Shartirt2661_watchdog(void *arg) 1740143407Sharti{ 1741143407Sharti struct rt2661_softc *sc = (struct rt2661_softc *)arg; 1742143407Sharti struct ifnet *ifp = sc->sc_ifp; 1743143407Sharti 1744143407Sharti RAL_LOCK_ASSERT(sc); 1745143407Sharti 1746143407Sharti KASSERT(ifp->if_drv_flags & IFF_DRV_RUNNING, ("not running")); 1747143407Sharti 17489254Sache if (sc->sc_invalid) /* card ejected */ 1749143407Sharti return; 17509254Sache 1751143407Sharti if (sc->sc_tx_timer > 0 && --sc->sc_tx_timer == 0) { 1752143407Sharti if_printf(ifp, "device timeout\n"); 17538874Srgrimes rt2661_init_locked(sc); 17541590Srgrimes ifp->if_oerrors++; 1755143407Sharti /* NB: callout is reset in rt2661_init() */ 1756143407Sharti return; 17571590Srgrimes } 1758143407Sharti callout_reset(&sc->watchdog_ch, hz, rt2661_watchdog, sc); 1759143407Sharti} 1760143407Sharti 1761143407Shartistatic int 1762143407Shartirt2661_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 1763143407Sharti{ 1764143407Sharti struct rt2661_softc *sc = ifp->if_softc; 1765143407Sharti struct ieee80211com *ic = ifp->if_l2com; 1766143407Sharti struct ifreq *ifr = (struct ifreq *) data; 1767143407Sharti int error = 0, startall = 0; 1768143407Sharti 1769143407Sharti switch (cmd) { 17701590Srgrimes case SIOCSIFFLAGS: 1771143407Sharti RAL_LOCK(sc); 1772143407Sharti if (ifp->if_flags & IFF_UP) { 1773143407Sharti if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { 1774143407Sharti rt2661_init_locked(sc); 1775143407Sharti startall = 1; 1776143407Sharti } else 17771590Srgrimes rt2661_update_promisc(ifp); 1778143407Sharti } else { 17791590Srgrimes if (ifp->if_drv_flags & IFF_DRV_RUNNING) 1780143407Sharti rt2661_stop_locked(sc); 1781143407Sharti } 1782143407Sharti RAL_UNLOCK(sc); 1783143407Sharti if (startall) 17841590Srgrimes ieee80211_start_all(ic); 1785143407Sharti break; 17861590Srgrimes case SIOCGIFMEDIA: 1787143407Sharti error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd); 1788143407Sharti break; 17891590Srgrimes case SIOCGIFADDR: 1790143407Sharti error = ether_ioctl(ifp, cmd, data); 1791143407Sharti break; 1792143407Sharti default: 1793143407Sharti error = EINVAL; 1794143407Sharti break; 17951590Srgrimes } 1796143407Sharti return error; 1797143407Sharti} 17988874Srgrimes 1799143407Shartistatic void 1800143407Shartirt2661_bbp_write(struct rt2661_softc *sc, uint8_t reg, uint8_t val) 1801143407Sharti{ 1802143407Sharti uint32_t tmp; 1803143407Sharti int ntries; 1804143407Sharti 1805143407Sharti for (ntries = 0; ntries < 100; ntries++) { 1806143407Sharti if (!(RAL_READ(sc, RT2661_PHY_CSR3) & RT2661_BBP_BUSY)) 1807144020Sharti break; 1808143407Sharti DELAY(1); 1809143407Sharti } 1810143407Sharti if (ntries == 100) { 1811143407Sharti device_printf(sc->sc_dev, "could not write to BBP\n"); 1812143407Sharti return; 18131590Srgrimes } 1814143407Sharti 1815143407Sharti tmp = RT2661_BBP_BUSY | (reg & 0x7f) << 8 | val; 1816143407Sharti RAL_WRITE(sc, RT2661_PHY_CSR3, tmp); 1817143407Sharti 1818143407Sharti DPRINTFN(sc, 15, "BBP R%u <- 0x%02x\n", reg, val); 1819143407Sharti} 1820143407Sharti 1821143407Shartistatic uint8_t 1822143407Shartirt2661_bbp_read(struct rt2661_softc *sc, uint8_t reg) 18231590Srgrimes{ 1824143407Sharti uint32_t val; 1825143407Sharti int ntries; 1826143407Sharti 1827143407Sharti for (ntries = 0; ntries < 100; ntries++) { 18281590Srgrimes if (!(RAL_READ(sc, RT2661_PHY_CSR3) & RT2661_BBP_BUSY)) 1829143407Sharti break; 1830143407Sharti DELAY(1); 18311590Srgrimes } 1832143407Sharti if (ntries == 100) { 1833143407Sharti device_printf(sc->sc_dev, "could not read from BBP\n"); 1834143407Sharti return 0; 1835143407Sharti } 18361590Srgrimes 1837143407Sharti val = RT2661_BBP_BUSY | RT2661_BBP_READ | reg << 8; 18381590Srgrimes RAL_WRITE(sc, RT2661_PHY_CSR3, val); 1839143407Sharti 1840143407Sharti for (ntries = 0; ntries < 100; ntries++) { 1841143407Sharti val = RAL_READ(sc, RT2661_PHY_CSR3); 1842143407Sharti if (!(val & RT2661_BBP_BUSY)) 1843143407Sharti return val & 0xff; 1844143407Sharti DELAY(1); 1845143407Sharti } 1846143407Sharti 1847143407Sharti device_printf(sc->sc_dev, "could not read from BBP\n"); 184818730Ssteve return 0; 1849143407Sharti} 1850143407Sharti 1851143407Shartistatic void 1852143407Shartirt2661_rf_write(struct rt2661_softc *sc, uint8_t reg, uint32_t val) 1853143407Sharti{ 1854143407Sharti uint32_t tmp; 1855143407Sharti int ntries; 1856143407Sharti 18571590Srgrimes for (ntries = 0; ntries < 100; ntries++) { 1858143407Sharti if (!(RAL_READ(sc, RT2661_PHY_CSR4) & RT2661_RF_BUSY)) 1859143407Sharti break; 1860143407Sharti DELAY(1); 1861143407Sharti } 1862143407Sharti if (ntries == 100) { 1863143407Sharti device_printf(sc->sc_dev, "could not write to RF\n"); 1864143407Sharti return; 1865143407Sharti } 1866143407Sharti 1867143407Sharti tmp = RT2661_RF_BUSY | RT2661_RF_21BIT | (val & 0x1fffff) << 2 | 1868143407Sharti (reg & 3); 1869143407Sharti RAL_WRITE(sc, RT2661_PHY_CSR4, tmp); 1870143407Sharti 18711590Srgrimes /* remember last written value in sc */ 1872143407Sharti sc->rf_regs[reg] = val; 1873143407Sharti 187418730Ssteve DPRINTFN(sc, 15, "RF R[%u] <- 0x%05x\n", reg & 3, val & 0x1fffff); 1875143407Sharti} 1876143407Sharti 1877143407Shartistatic int 1878143407Shartirt2661_tx_cmd(struct rt2661_softc *sc, uint8_t cmd, uint16_t arg) 1879143407Sharti{ 1880143407Sharti if (RAL_READ(sc, RT2661_H2M_MAILBOX_CSR) & RT2661_H2M_BUSY) 18811590Srgrimes return EIO; /* there is already a command pending */ 18828874Srgrimes 1883143407Sharti RAL_WRITE(sc, RT2661_H2M_MAILBOX_CSR, 1884143407Sharti RT2661_H2M_BUSY | RT2661_TOKEN_NO_INTR << 16 | arg); 1885143407Sharti 1886143407Sharti RAL_WRITE(sc, RT2661_HOST_CMD_CSR, RT2661_KICK_CMD | cmd); 1887143407Sharti 18881590Srgrimes return 0; 1889143407Sharti} 1890143407Sharti 1891143407Shartistatic void 1892143407Shartirt2661_select_antenna(struct rt2661_softc *sc) 1893143407Sharti{ 1894143407Sharti uint8_t bbp4, bbp77; 1895143407Sharti uint32_t tmp; 1896143407Sharti 1897143407Sharti bbp4 = rt2661_bbp_read(sc, 4); 1898143407Sharti bbp77 = rt2661_bbp_read(sc, 77); 1899143407Sharti 1900143407Sharti /* TBD */ 1901143407Sharti 19025814Sjkh /* make sure Rx is disabled before switching antenna */ 19031590Srgrimes tmp = RAL_READ(sc, RT2661_TXRX_CSR0); 19041590Srgrimes RAL_WRITE(sc, RT2661_TXRX_CSR0, tmp | RT2661_DISABLE_RX); 1905143407Sharti 1906143407Sharti rt2661_bbp_write(sc, 4, bbp4); 1907143407Sharti rt2661_bbp_write(sc, 77, bbp77); 1908143407Sharti 1909143407Sharti /* restore Rx filter */ 1910143407Sharti RAL_WRITE(sc, RT2661_TXRX_CSR0, tmp); 1911143407Sharti} 19121590Srgrimes 1913143407Sharti/* 1914143407Sharti * Enable multi-rate retries for frames sent at OFDM rates. 1915143407Sharti * In 802.11b/g mode, allow fallback to CCK rates. 1916143407Sharti */ 1917143407Shartistatic void 1918143407Shartirt2661_enable_mrr(struct rt2661_softc *sc) 1919143407Sharti{ 1920143407Sharti struct ifnet *ifp = sc->sc_ifp; 1921143407Sharti struct ieee80211com *ic = ifp->if_l2com; 1922143407Sharti uint32_t tmp; 19231590Srgrimes 1924143407Sharti tmp = RAL_READ(sc, RT2661_TXRX_CSR4); 1925143407Sharti 1926143407Sharti tmp &= ~RT2661_MRR_CCK_FALLBACK; 19271590Srgrimes if (!IEEE80211_IS_CHAN_5GHZ(ic->ic_bsschan)) 1928143407Sharti tmp |= RT2661_MRR_CCK_FALLBACK; 1929143407Sharti tmp |= RT2661_MRR_ENABLED; 19308874Srgrimes 1931143407Sharti RAL_WRITE(sc, RT2661_TXRX_CSR4, tmp); 1932143407Sharti} 1933143407Sharti 1934143407Shartistatic void 19351590Srgrimesrt2661_set_txpreamble(struct rt2661_softc *sc) 1936143407Sharti{ 1937143407Sharti struct ifnet *ifp = sc->sc_ifp; 1938143407Sharti struct ieee80211com *ic = ifp->if_l2com; 19391590Srgrimes uint32_t tmp; 1940143407Sharti 1941143407Sharti tmp = RAL_READ(sc, RT2661_TXRX_CSR4); 19421590Srgrimes 1943143407Sharti tmp &= ~RT2661_SHORT_PREAMBLE; 1944143407Sharti if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) 1945143407Sharti tmp |= RT2661_SHORT_PREAMBLE; 1946143407Sharti 1947143407Sharti RAL_WRITE(sc, RT2661_TXRX_CSR4, tmp); 1948143407Sharti} 1949143407Sharti 1950143407Shartistatic void 1951143407Shartirt2661_set_basicrates(struct rt2661_softc *sc, 1952143407Sharti const struct ieee80211_rateset *rs) 1953143407Sharti{ 1954143407Sharti#define RV(r) ((r) & IEEE80211_RATE_VAL) 19551590Srgrimes struct ifnet *ifp = sc->sc_ifp; 1956143407Sharti struct ieee80211com *ic = ifp->if_l2com; 1957143407Sharti uint32_t mask = 0; 1958143407Sharti uint8_t rate; 19591590Srgrimes int i, j; 19601590Srgrimes 1961143407Sharti for (i = 0; i < rs->rs_nrates; i++) { 1962143407Sharti rate = rs->rs_rates[i]; 1963143407Sharti 1964143407Sharti if (!(rate & IEEE80211_RATE_BASIC)) 19651590Srgrimes continue; 1966143407Sharti 1967143407Sharti /* 1968143407Sharti * Find h/w rate index. We know it exists because the rate 1969143407Sharti * set has already been negotiated. 1970143407Sharti */ 19711590Srgrimes for (j = 0; ic->ic_sup_rates[IEEE80211_MODE_11G].rs_rates[j] != RV(rate); j++); 1972143407Sharti 1973143407Sharti mask |= 1 << j; 1974143407Sharti } 1975143407Sharti 1976143407Sharti RAL_WRITE(sc, RT2661_TXRX_CSR5, mask); 1977143407Sharti 1978143407Sharti DPRINTF(sc, "Setting basic rate mask to 0x%x\n", mask); 1979143407Sharti#undef RV 19801590Srgrimes} 1981143407Sharti 1982143407Sharti/* 19835814Sjkh * Reprogram MAC/BBP to switch to a new band. Values taken from the reference 1984143407Sharti * driver. 1985143407Sharti */ 19861590Srgrimesstatic void 19878874Srgrimesrt2661_select_band(struct rt2661_softc *sc, struct ieee80211_channel *c) 19881590Srgrimes{ 19891590Srgrimes uint8_t bbp17, bbp35, bbp96, bbp97, bbp98, bbp104; 19901590Srgrimes uint32_t tmp; 19911590Srgrimes 19921590Srgrimes /* update all BBP registers that depend on the band */ 19931590Srgrimes bbp17 = 0x20; bbp96 = 0x48; bbp104 = 0x2c; 19941590Srgrimes bbp35 = 0x50; bbp97 = 0x48; bbp98 = 0x48; 19951590Srgrimes if (IEEE80211_IS_CHAN_5GHZ(c)) { 19961590Srgrimes bbp17 += 0x08; bbp96 += 0x10; bbp104 += 0x0c; 19971590Srgrimes bbp35 += 0x10; bbp97 += 0x10; bbp98 += 0x10; 19981590Srgrimes } 19991590Srgrimes if ((IEEE80211_IS_CHAN_2GHZ(c) && sc->ext_2ghz_lna) || 20001590Srgrimes (IEEE80211_IS_CHAN_5GHZ(c) && sc->ext_5ghz_lna)) { 20011590Srgrimes bbp17 += 0x10; bbp96 += 0x10; bbp104 += 0x10; 20021590Srgrimes } 20031590Srgrimes 20041590Srgrimes rt2661_bbp_write(sc, 17, bbp17); 20051590Srgrimes rt2661_bbp_write(sc, 96, bbp96); 20061590Srgrimes rt2661_bbp_write(sc, 104, bbp104); 20071590Srgrimes 20081590Srgrimes if ((IEEE80211_IS_CHAN_2GHZ(c) && sc->ext_2ghz_lna) || 20091590Srgrimes (IEEE80211_IS_CHAN_5GHZ(c) && sc->ext_5ghz_lna)) { 20101590Srgrimes rt2661_bbp_write(sc, 75, 0x80); 20111590Srgrimes rt2661_bbp_write(sc, 86, 0x80); 20121590Srgrimes rt2661_bbp_write(sc, 88, 0x80); 20131590Srgrimes } 20141590Srgrimes 20151590Srgrimes rt2661_bbp_write(sc, 35, bbp35); 2016104696Sjmallett rt2661_bbp_write(sc, 97, bbp97); 20175814Sjkh rt2661_bbp_write(sc, 98, bbp98); 20188874Srgrimes 2019143407Sharti tmp = RAL_READ(sc, RT2661_PHY_CSR0); 2020143407Sharti tmp &= ~(RT2661_PA_PE_2GHZ | RT2661_PA_PE_5GHZ); 2021143407Sharti if (IEEE80211_IS_CHAN_2GHZ(c)) 20225814Sjkh tmp |= RT2661_PA_PE_2GHZ; 20235814Sjkh else 20245814Sjkh tmp |= RT2661_PA_PE_5GHZ; 20255814Sjkh RAL_WRITE(sc, RT2661_PHY_CSR0, tmp); 2026138512Sharti} 20271590Srgrimes 2028138232Shartistatic void 2029143407Shartirt2661_set_chan(struct rt2661_softc *sc, struct ieee80211_channel *c) 2030143407Sharti{ 2031143407Sharti struct ifnet *ifp = sc->sc_ifp; 2032143407Sharti struct ieee80211com *ic = ifp->if_l2com; 2033143407Sharti const struct rfprog *rfprog; 2034143407Sharti uint8_t bbp3, bbp94 = RT2661_BBPR94_DEFAULT; 2035143407Sharti int8_t power; 2036143407Sharti u_int i, chan; 20378874Srgrimes 2038143407Sharti chan = ieee80211_chan2ieee(ic, c); 20398874Srgrimes KASSERT(chan != 0 && chan != IEEE80211_CHAN_ANY, ("chan 0x%x", chan)); 2040143407Sharti 2041143407Sharti /* select the appropriate RF settings based on what EEPROM says */ 20428874Srgrimes rfprog = (sc->rfprog == 0) ? rt2661_rf5225_1 : rt2661_rf5225_2; 2043143407Sharti 2044143407Sharti /* find the settings for this channel (we know it exists) */ 2045143407Sharti for (i = 0; rfprog[i].chan != chan; i++); 2046143407Sharti 2047143407Sharti power = sc->txpow[i]; 2048143407Sharti if (power < 0) { 2049143407Sharti bbp94 += power; 2050143407Sharti power = 0; 2051143407Sharti } else if (power > 31) { 2052143407Sharti bbp94 += power - 31; 2053143407Sharti power = 31; 2054143911Sharti } 2055143407Sharti 2056143407Sharti /* 2057143911Sharti * If we are switching from the 2GHz band to the 5GHz band or 2058143911Sharti * vice-versa, BBP registers need to be reprogrammed. 2059143407Sharti */ 2060143407Sharti if (c->ic_flags != sc->sc_curchan->ic_flags) { 2061143407Sharti rt2661_select_band(sc, c); 2062143407Sharti rt2661_select_antenna(sc); 2063143407Sharti } 2064143407Sharti sc->sc_curchan = c; 2065143407Sharti 2066143407Sharti rt2661_rf_write(sc, RAL_RF1, rfprog[i].r1); 2067143407Sharti rt2661_rf_write(sc, RAL_RF2, rfprog[i].r2); 2068143407Sharti rt2661_rf_write(sc, RAL_RF3, rfprog[i].r3 | power << 7); 2069143407Sharti rt2661_rf_write(sc, RAL_RF4, rfprog[i].r4 | sc->rffreq << 10); 2070143407Sharti 2071143407Sharti DELAY(200); 2072143407Sharti 20731590Srgrimes rt2661_rf_write(sc, RAL_RF1, rfprog[i].r1); 2074143407Sharti rt2661_rf_write(sc, RAL_RF2, rfprog[i].r2); 20751590Srgrimes rt2661_rf_write(sc, RAL_RF3, rfprog[i].r3 | power << 7 | 1); 20761590Srgrimes rt2661_rf_write(sc, RAL_RF4, rfprog[i].r4 | sc->rffreq << 10); 20771590Srgrimes 20781590Srgrimes DELAY(200); 20791590Srgrimes 20801590Srgrimes rt2661_rf_write(sc, RAL_RF1, rfprog[i].r1); 20811590Srgrimes rt2661_rf_write(sc, RAL_RF2, rfprog[i].r2); 20821590Srgrimes rt2661_rf_write(sc, RAL_RF3, rfprog[i].r3 | power << 7); 20831590Srgrimes rt2661_rf_write(sc, RAL_RF4, rfprog[i].r4 | sc->rffreq << 10); 20841590Srgrimes 20851590Srgrimes /* enable smart mode for MIMO-capable RFs */ 20861590Srgrimes bbp3 = rt2661_bbp_read(sc, 3); 20871590Srgrimes 20881590Srgrimes bbp3 &= ~RT2661_SMART_MODE; 20891590Srgrimes if (sc->rf_rev == RT2661_RF_5325 || sc->rf_rev == RT2661_RF_2529) 20901590Srgrimes bbp3 |= RT2661_SMART_MODE; 20911590Srgrimes 20921590Srgrimes rt2661_bbp_write(sc, 3, bbp3); 20931590Srgrimes 20941590Srgrimes if (bbp94 != RT2661_BBPR94_DEFAULT) 20951590Srgrimes rt2661_bbp_write(sc, 94, bbp94); 2096104696Sjmallett 20971590Srgrimes /* 5GHz radio needs a 1ms delay here */ 2098143407Sharti if (IEEE80211_IS_CHAN_5GHZ(c)) 20991590Srgrimes DELAY(1000); 2100143911Sharti} 2101143407Sharti 2102143407Shartistatic void 2103143911Shartirt2661_set_bssid(struct rt2661_softc *sc, const uint8_t *bssid) 21041590Srgrimes{ 2105143911Sharti uint32_t tmp; 2106143911Sharti 2107143911Sharti tmp = bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24; 2108143911Sharti RAL_WRITE(sc, RT2661_MAC_CSR4, tmp); 2109143911Sharti 2110143911Sharti tmp = bssid[4] | bssid[5] << 8 | RT2661_ONE_BSSID << 16; 2111143911Sharti RAL_WRITE(sc, RT2661_MAC_CSR5, tmp); 2112143911Sharti} 2113143911Sharti 2114143911Shartistatic void 2115143911Shartirt2661_set_macaddr(struct rt2661_softc *sc, const uint8_t *addr) 21161590Srgrimes{ 21171590Srgrimes uint32_t tmp; 21181590Srgrimes 21191590Srgrimes tmp = addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24; 21201590Srgrimes RAL_WRITE(sc, RT2661_MAC_CSR2, tmp); 21211590Srgrimes 21221590Srgrimes tmp = addr[4] | addr[5] << 8; 21231590Srgrimes RAL_WRITE(sc, RT2661_MAC_CSR3, tmp); 21241590Srgrimes} 21251590Srgrimes 21261590Srgrimesstatic void 21271590Srgrimesrt2661_update_promisc(struct ifnet *ifp) 21281590Srgrimes{ 21291590Srgrimes struct rt2661_softc *sc = ifp->if_softc; 21301590Srgrimes uint32_t tmp; 2131138232Sharti 21321590Srgrimes tmp = RAL_READ(sc, RT2661_TXRX_CSR0); 2133138232Sharti 2134143407Sharti tmp &= ~RT2661_DROP_NOT_TO_ME; 2135143407Sharti if (!(ifp->if_flags & IFF_PROMISC)) 2136143407Sharti tmp |= RT2661_DROP_NOT_TO_ME; 2137143407Sharti 2138143407Sharti RAL_WRITE(sc, RT2661_TXRX_CSR0, tmp); 2139143407Sharti 2140143407Sharti DPRINTF(sc, "%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ? 21411590Srgrimes "entering" : "leaving"); 2142143407Sharti} 2143143407Sharti 2144144020Sharti/* 2145144020Sharti * Update QoS (802.11e) settings for each h/w Tx ring. 2146143407Sharti */ 2147143407Shartistatic int 2148143407Shartirt2661_wme_update(struct ieee80211com *ic) 2149143407Sharti{ 2150143407Sharti struct rt2661_softc *sc = ic->ic_ifp->if_softc; 2151143407Sharti const struct wmeParams *wmep; 21521590Srgrimes 21531590Srgrimes wmep = ic->ic_wme.wme_chanParams.cap_wmeParams; 21541590Srgrimes 21551590Srgrimes /* XXX: not sure about shifts. */ 2156143414Sharti /* XXX: the reference driver plays with AC_VI settings too. */ 2157143414Sharti 21585814Sjkh /* update TxOp */ 2159143414Sharti RAL_WRITE(sc, RT2661_AC_TXOP_CSR0, 2160143414Sharti wmep[WME_AC_BE].wmep_txopLimit << 16 | 2161143414Sharti wmep[WME_AC_BK].wmep_txopLimit); 2162143414Sharti RAL_WRITE(sc, RT2661_AC_TXOP_CSR1, 2163138232Sharti wmep[WME_AC_VI].wmep_txopLimit << 16 | 2164143414Sharti wmep[WME_AC_VO].wmep_txopLimit); 2165143414Sharti 2166143414Sharti /* update CWmin */ 2167143414Sharti RAL_WRITE(sc, RT2661_CWMIN_CSR, 2168143414Sharti wmep[WME_AC_BE].wmep_logcwmin << 12 | 2169143414Sharti wmep[WME_AC_BK].wmep_logcwmin << 8 | 21701590Srgrimes wmep[WME_AC_VI].wmep_logcwmin << 4 | 2171143414Sharti wmep[WME_AC_VO].wmep_logcwmin); 2172143414Sharti 2173143414Sharti /* update CWmax */ 2174143414Sharti RAL_WRITE(sc, RT2661_CWMAX_CSR, 21751590Srgrimes wmep[WME_AC_BE].wmep_logcwmax << 12 | 2176143414Sharti wmep[WME_AC_BK].wmep_logcwmax << 8 | 2177143414Sharti wmep[WME_AC_VI].wmep_logcwmax << 4 | 2178146184Sharti wmep[WME_AC_VO].wmep_logcwmax); 2179143407Sharti 21801590Srgrimes /* update Aifsn */ 2181143414Sharti RAL_WRITE(sc, RT2661_AIFSN_CSR, 2182143414Sharti wmep[WME_AC_BE].wmep_aifsn << 12 | 2183143414Sharti wmep[WME_AC_BK].wmep_aifsn << 8 | 21841590Srgrimes wmep[WME_AC_VI].wmep_aifsn << 4 | 2185143414Sharti wmep[WME_AC_VO].wmep_aifsn); 2186143414Sharti 2187143414Sharti return 0; 21881590Srgrimes} 2189143414Sharti 2190144020Shartistatic void 21911590Srgrimesrt2661_update_slot(struct ifnet *ifp) 2192143414Sharti{ 2193143414Sharti struct rt2661_softc *sc = ifp->if_softc; 2194138232Sharti struct ieee80211com *ic = ifp->if_l2com; 2195143407Sharti uint8_t slottime; 2196143414Sharti uint32_t tmp; 2197143414Sharti 2198143414Sharti slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20; 2199143414Sharti 2200143414Sharti tmp = RAL_READ(sc, RT2661_MAC_CSR9); 2201143414Sharti tmp = (tmp & ~0xff) | slottime; 2202143414Sharti RAL_WRITE(sc, RT2661_MAC_CSR9, tmp); 2203143414Sharti} 2204143414Sharti 22051590Srgrimesstatic const char * 2206rt2661_get_rf(int rev) 2207{ 2208 switch (rev) { 2209 case RT2661_RF_5225: return "RT5225"; 2210 case RT2661_RF_5325: return "RT5325 (MIMO XR)"; 2211 case RT2661_RF_2527: return "RT2527"; 2212 case RT2661_RF_2529: return "RT2529 (MIMO XR)"; 2213 default: return "unknown"; 2214 } 2215} 2216 2217static void 2218rt2661_read_eeprom(struct rt2661_softc *sc, uint8_t macaddr[IEEE80211_ADDR_LEN]) 2219{ 2220 uint16_t val; 2221 int i; 2222 2223 /* read MAC address */ 2224 val = rt2661_eeprom_read(sc, RT2661_EEPROM_MAC01); 2225 macaddr[0] = val & 0xff; 2226 macaddr[1] = val >> 8; 2227 2228 val = rt2661_eeprom_read(sc, RT2661_EEPROM_MAC23); 2229 macaddr[2] = val & 0xff; 2230 macaddr[3] = val >> 8; 2231 2232 val = rt2661_eeprom_read(sc, RT2661_EEPROM_MAC45); 2233 macaddr[4] = val & 0xff; 2234 macaddr[5] = val >> 8; 2235 2236 val = rt2661_eeprom_read(sc, RT2661_EEPROM_ANTENNA); 2237 /* XXX: test if different from 0xffff? */ 2238 sc->rf_rev = (val >> 11) & 0x1f; 2239 sc->hw_radio = (val >> 10) & 0x1; 2240 sc->rx_ant = (val >> 4) & 0x3; 2241 sc->tx_ant = (val >> 2) & 0x3; 2242 sc->nb_ant = val & 0x3; 2243 2244 DPRINTF(sc, "RF revision=%d\n", sc->rf_rev); 2245 2246 val = rt2661_eeprom_read(sc, RT2661_EEPROM_CONFIG2); 2247 sc->ext_5ghz_lna = (val >> 6) & 0x1; 2248 sc->ext_2ghz_lna = (val >> 4) & 0x1; 2249 2250 DPRINTF(sc, "External 2GHz LNA=%d\nExternal 5GHz LNA=%d\n", 2251 sc->ext_2ghz_lna, sc->ext_5ghz_lna); 2252 2253 val = rt2661_eeprom_read(sc, RT2661_EEPROM_RSSI_2GHZ_OFFSET); 2254 if ((val & 0xff) != 0xff) 2255 sc->rssi_2ghz_corr = (int8_t)(val & 0xff); /* signed */ 2256 2257 /* Only [-10, 10] is valid */ 2258 if (sc->rssi_2ghz_corr < -10 || sc->rssi_2ghz_corr > 10) 2259 sc->rssi_2ghz_corr = 0; 2260 2261 val = rt2661_eeprom_read(sc, RT2661_EEPROM_RSSI_5GHZ_OFFSET); 2262 if ((val & 0xff) != 0xff) 2263 sc->rssi_5ghz_corr = (int8_t)(val & 0xff); /* signed */ 2264 2265 /* Only [-10, 10] is valid */ 2266 if (sc->rssi_5ghz_corr < -10 || sc->rssi_5ghz_corr > 10) 2267 sc->rssi_5ghz_corr = 0; 2268 2269 /* adjust RSSI correction for external low-noise amplifier */ 2270 if (sc->ext_2ghz_lna) 2271 sc->rssi_2ghz_corr -= 14; 2272 if (sc->ext_5ghz_lna) 2273 sc->rssi_5ghz_corr -= 14; 2274 2275 DPRINTF(sc, "RSSI 2GHz corr=%d\nRSSI 5GHz corr=%d\n", 2276 sc->rssi_2ghz_corr, sc->rssi_5ghz_corr); 2277 2278 val = rt2661_eeprom_read(sc, RT2661_EEPROM_FREQ_OFFSET); 2279 if ((val >> 8) != 0xff) 2280 sc->rfprog = (val >> 8) & 0x3; 2281 if ((val & 0xff) != 0xff) 2282 sc->rffreq = val & 0xff; 2283 2284 DPRINTF(sc, "RF prog=%d\nRF freq=%d\n", sc->rfprog, sc->rffreq); 2285 2286 /* read Tx power for all a/b/g channels */ 2287 for (i = 0; i < 19; i++) { 2288 val = rt2661_eeprom_read(sc, RT2661_EEPROM_TXPOWER + i); 2289 sc->txpow[i * 2] = (int8_t)(val >> 8); /* signed */ 2290 DPRINTF(sc, "Channel=%d Tx power=%d\n", 2291 rt2661_rf5225_1[i * 2].chan, sc->txpow[i * 2]); 2292 sc->txpow[i * 2 + 1] = (int8_t)(val & 0xff); /* signed */ 2293 DPRINTF(sc, "Channel=%d Tx power=%d\n", 2294 rt2661_rf5225_1[i * 2 + 1].chan, sc->txpow[i * 2 + 1]); 2295 } 2296 2297 /* read vendor-specific BBP values */ 2298 for (i = 0; i < 16; i++) { 2299 val = rt2661_eeprom_read(sc, RT2661_EEPROM_BBP_BASE + i); 2300 if (val == 0 || val == 0xffff) 2301 continue; /* skip invalid entries */ 2302 sc->bbp_prom[i].reg = val >> 8; 2303 sc->bbp_prom[i].val = val & 0xff; 2304 DPRINTF(sc, "BBP R%d=%02x\n", sc->bbp_prom[i].reg, 2305 sc->bbp_prom[i].val); 2306 } 2307} 2308 2309static int 2310rt2661_bbp_init(struct rt2661_softc *sc) 2311{ 2312#define N(a) (sizeof (a) / sizeof ((a)[0])) 2313 int i, ntries; 2314 uint8_t val; 2315 2316 /* wait for BBP to be ready */ 2317 for (ntries = 0; ntries < 100; ntries++) { 2318 val = rt2661_bbp_read(sc, 0); 2319 if (val != 0 && val != 0xff) 2320 break; 2321 DELAY(100); 2322 } 2323 if (ntries == 100) { 2324 device_printf(sc->sc_dev, "timeout waiting for BBP\n"); 2325 return EIO; 2326 } 2327 2328 /* initialize BBP registers to default values */ 2329 for (i = 0; i < N(rt2661_def_bbp); i++) { 2330 rt2661_bbp_write(sc, rt2661_def_bbp[i].reg, 2331 rt2661_def_bbp[i].val); 2332 } 2333 2334 /* write vendor-specific BBP values (from EEPROM) */ 2335 for (i = 0; i < 16; i++) { 2336 if (sc->bbp_prom[i].reg == 0) 2337 continue; 2338 rt2661_bbp_write(sc, sc->bbp_prom[i].reg, sc->bbp_prom[i].val); 2339 } 2340 2341 return 0; 2342#undef N 2343} 2344 2345static void 2346rt2661_init_locked(struct rt2661_softc *sc) 2347{ 2348#define N(a) (sizeof (a) / sizeof ((a)[0])) 2349 struct ifnet *ifp = sc->sc_ifp; 2350 struct ieee80211com *ic = ifp->if_l2com; 2351 uint32_t tmp, sta[3]; 2352 int i, error, ntries; 2353 2354 RAL_LOCK_ASSERT(sc); 2355 2356 if ((sc->sc_flags & RAL_FW_LOADED) == 0) { 2357 error = rt2661_load_microcode(sc); 2358 if (error != 0) { 2359 if_printf(ifp, 2360 "%s: could not load 8051 microcode, error %d\n", 2361 __func__, error); 2362 return; 2363 } 2364 sc->sc_flags |= RAL_FW_LOADED; 2365 } 2366 2367 rt2661_stop_locked(sc); 2368 2369 /* initialize Tx rings */ 2370 RAL_WRITE(sc, RT2661_AC1_BASE_CSR, sc->txq[1].physaddr); 2371 RAL_WRITE(sc, RT2661_AC0_BASE_CSR, sc->txq[0].physaddr); 2372 RAL_WRITE(sc, RT2661_AC2_BASE_CSR, sc->txq[2].physaddr); 2373 RAL_WRITE(sc, RT2661_AC3_BASE_CSR, sc->txq[3].physaddr); 2374 2375 /* initialize Mgt ring */ 2376 RAL_WRITE(sc, RT2661_MGT_BASE_CSR, sc->mgtq.physaddr); 2377 2378 /* initialize Rx ring */ 2379 RAL_WRITE(sc, RT2661_RX_BASE_CSR, sc->rxq.physaddr); 2380 2381 /* initialize Tx rings sizes */ 2382 RAL_WRITE(sc, RT2661_TX_RING_CSR0, 2383 RT2661_TX_RING_COUNT << 24 | 2384 RT2661_TX_RING_COUNT << 16 | 2385 RT2661_TX_RING_COUNT << 8 | 2386 RT2661_TX_RING_COUNT); 2387 2388 RAL_WRITE(sc, RT2661_TX_RING_CSR1, 2389 RT2661_TX_DESC_WSIZE << 16 | 2390 RT2661_TX_RING_COUNT << 8 | /* XXX: HCCA ring unused */ 2391 RT2661_MGT_RING_COUNT); 2392 2393 /* initialize Rx rings */ 2394 RAL_WRITE(sc, RT2661_RX_RING_CSR, 2395 RT2661_RX_DESC_BACK << 16 | 2396 RT2661_RX_DESC_WSIZE << 8 | 2397 RT2661_RX_RING_COUNT); 2398 2399 /* XXX: some magic here */ 2400 RAL_WRITE(sc, RT2661_TX_DMA_DST_CSR, 0xaa); 2401 2402 /* load base addresses of all 5 Tx rings (4 data + 1 mgt) */ 2403 RAL_WRITE(sc, RT2661_LOAD_TX_RING_CSR, 0x1f); 2404 2405 /* load base address of Rx ring */ 2406 RAL_WRITE(sc, RT2661_RX_CNTL_CSR, 2); 2407 2408 /* initialize MAC registers to default values */ 2409 for (i = 0; i < N(rt2661_def_mac); i++) 2410 RAL_WRITE(sc, rt2661_def_mac[i].reg, rt2661_def_mac[i].val); 2411 2412 rt2661_set_macaddr(sc, IF_LLADDR(ifp)); 2413 2414 /* set host ready */ 2415 RAL_WRITE(sc, RT2661_MAC_CSR1, 3); 2416 RAL_WRITE(sc, RT2661_MAC_CSR1, 0); 2417 2418 /* wait for BBP/RF to wakeup */ 2419 for (ntries = 0; ntries < 1000; ntries++) { 2420 if (RAL_READ(sc, RT2661_MAC_CSR12) & 8) 2421 break; 2422 DELAY(1000); 2423 } 2424 if (ntries == 1000) { 2425 printf("timeout waiting for BBP/RF to wakeup\n"); 2426 rt2661_stop_locked(sc); 2427 return; 2428 } 2429 2430 if (rt2661_bbp_init(sc) != 0) { 2431 rt2661_stop_locked(sc); 2432 return; 2433 } 2434 2435 /* select default channel */ 2436 sc->sc_curchan = ic->ic_curchan; 2437 rt2661_select_band(sc, sc->sc_curchan); 2438 rt2661_select_antenna(sc); 2439 rt2661_set_chan(sc, sc->sc_curchan); 2440 2441 /* update Rx filter */ 2442 tmp = RAL_READ(sc, RT2661_TXRX_CSR0) & 0xffff; 2443 2444 tmp |= RT2661_DROP_PHY_ERROR | RT2661_DROP_CRC_ERROR; 2445 if (ic->ic_opmode != IEEE80211_M_MONITOR) { 2446 tmp |= RT2661_DROP_CTL | RT2661_DROP_VER_ERROR | 2447 RT2661_DROP_ACKCTS; 2448 if (ic->ic_opmode != IEEE80211_M_HOSTAP) 2449 tmp |= RT2661_DROP_TODS; 2450 if (!(ifp->if_flags & IFF_PROMISC)) 2451 tmp |= RT2661_DROP_NOT_TO_ME; 2452 } 2453 2454 RAL_WRITE(sc, RT2661_TXRX_CSR0, tmp); 2455 2456 /* clear STA registers */ 2457 RAL_READ_REGION_4(sc, RT2661_STA_CSR0, sta, N(sta)); 2458 2459 /* initialize ASIC */ 2460 RAL_WRITE(sc, RT2661_MAC_CSR1, 4); 2461 2462 /* clear any pending interrupt */ 2463 RAL_WRITE(sc, RT2661_INT_SOURCE_CSR, 0xffffffff); 2464 2465 /* enable interrupts */ 2466 RAL_WRITE(sc, RT2661_INT_MASK_CSR, 0x0000ff10); 2467 RAL_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0); 2468 2469 /* kick Rx */ 2470 RAL_WRITE(sc, RT2661_RX_CNTL_CSR, 1); 2471 2472 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 2473 ifp->if_drv_flags |= IFF_DRV_RUNNING; 2474 2475 callout_reset(&sc->watchdog_ch, hz, rt2661_watchdog, sc); 2476#undef N 2477} 2478 2479static void 2480rt2661_init(void *priv) 2481{ 2482 struct rt2661_softc *sc = priv; 2483 struct ifnet *ifp = sc->sc_ifp; 2484 struct ieee80211com *ic = ifp->if_l2com; 2485 2486 RAL_LOCK(sc); 2487 rt2661_init_locked(sc); 2488 RAL_UNLOCK(sc); 2489 2490 if (ifp->if_drv_flags & IFF_DRV_RUNNING) 2491 ieee80211_start_all(ic); /* start all vap's */ 2492} 2493 2494void 2495rt2661_stop_locked(struct rt2661_softc *sc) 2496{ 2497 struct ifnet *ifp = sc->sc_ifp; 2498 uint32_t tmp; 2499 volatile int *flags = &sc->sc_flags; 2500 2501 while (*flags & RAL_INPUT_RUNNING) 2502 msleep(sc, &sc->sc_mtx, 0, "ralrunning", hz/10); 2503 2504 callout_stop(&sc->watchdog_ch); 2505 sc->sc_tx_timer = 0; 2506 2507 if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 2508 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 2509 2510 /* abort Tx (for all 5 Tx rings) */ 2511 RAL_WRITE(sc, RT2661_TX_CNTL_CSR, 0x1f << 16); 2512 2513 /* disable Rx (value remains after reset!) */ 2514 tmp = RAL_READ(sc, RT2661_TXRX_CSR0); 2515 RAL_WRITE(sc, RT2661_TXRX_CSR0, tmp | RT2661_DISABLE_RX); 2516 2517 /* reset ASIC */ 2518 RAL_WRITE(sc, RT2661_MAC_CSR1, 3); 2519 RAL_WRITE(sc, RT2661_MAC_CSR1, 0); 2520 2521 /* disable interrupts */ 2522 RAL_WRITE(sc, RT2661_INT_MASK_CSR, 0xffffffff); 2523 RAL_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0xffffffff); 2524 2525 /* clear any pending interrupt */ 2526 RAL_WRITE(sc, RT2661_INT_SOURCE_CSR, 0xffffffff); 2527 RAL_WRITE(sc, RT2661_MCU_INT_SOURCE_CSR, 0xffffffff); 2528 2529 /* reset Tx and Rx rings */ 2530 rt2661_reset_tx_ring(sc, &sc->txq[0]); 2531 rt2661_reset_tx_ring(sc, &sc->txq[1]); 2532 rt2661_reset_tx_ring(sc, &sc->txq[2]); 2533 rt2661_reset_tx_ring(sc, &sc->txq[3]); 2534 rt2661_reset_tx_ring(sc, &sc->mgtq); 2535 rt2661_reset_rx_ring(sc, &sc->rxq); 2536 } 2537} 2538 2539void 2540rt2661_stop(void *priv) 2541{ 2542 struct rt2661_softc *sc = priv; 2543 2544 RAL_LOCK(sc); 2545 rt2661_stop_locked(sc); 2546 RAL_UNLOCK(sc); 2547} 2548 2549static int 2550rt2661_load_microcode(struct rt2661_softc *sc) 2551{ 2552 struct ifnet *ifp = sc->sc_ifp; 2553 const struct firmware *fp; 2554 const char *imagename; 2555 int ntries, error; 2556 2557 RAL_LOCK_ASSERT(sc); 2558 2559 switch (sc->sc_id) { 2560 case 0x0301: imagename = "rt2561sfw"; break; 2561 case 0x0302: imagename = "rt2561fw"; break; 2562 case 0x0401: imagename = "rt2661fw"; break; 2563 default: 2564 if_printf(ifp, "%s: unexpected pci device id 0x%x, " 2565 "don't know how to retrieve firmware\n", 2566 __func__, sc->sc_id); 2567 return EINVAL; 2568 } 2569 RAL_UNLOCK(sc); 2570 fp = firmware_get(imagename); 2571 RAL_LOCK(sc); 2572 if (fp == NULL) { 2573 if_printf(ifp, "%s: unable to retrieve firmware image %s\n", 2574 __func__, imagename); 2575 return EINVAL; 2576 } 2577 2578 /* 2579 * Load 8051 microcode into NIC. 2580 */ 2581 /* reset 8051 */ 2582 RAL_WRITE(sc, RT2661_MCU_CNTL_CSR, RT2661_MCU_RESET); 2583 2584 /* cancel any pending Host to MCU command */ 2585 RAL_WRITE(sc, RT2661_H2M_MAILBOX_CSR, 0); 2586 RAL_WRITE(sc, RT2661_M2H_CMD_DONE_CSR, 0xffffffff); 2587 RAL_WRITE(sc, RT2661_HOST_CMD_CSR, 0); 2588 2589 /* write 8051's microcode */ 2590 RAL_WRITE(sc, RT2661_MCU_CNTL_CSR, RT2661_MCU_RESET | RT2661_MCU_SEL); 2591 RAL_WRITE_REGION_1(sc, RT2661_MCU_CODE_BASE, fp->data, fp->datasize); 2592 RAL_WRITE(sc, RT2661_MCU_CNTL_CSR, RT2661_MCU_RESET); 2593 2594 /* kick 8051's ass */ 2595 RAL_WRITE(sc, RT2661_MCU_CNTL_CSR, 0); 2596 2597 /* wait for 8051 to initialize */ 2598 for (ntries = 0; ntries < 500; ntries++) { 2599 if (RAL_READ(sc, RT2661_MCU_CNTL_CSR) & RT2661_MCU_READY) 2600 break; 2601 DELAY(100); 2602 } 2603 if (ntries == 500) { 2604 if_printf(ifp, "%s: timeout waiting for MCU to initialize\n", 2605 __func__); 2606 error = EIO; 2607 } else 2608 error = 0; 2609 2610 firmware_put(fp, FIRMWARE_UNLOAD); 2611 return error; 2612} 2613 2614#ifdef notyet 2615/* 2616 * Dynamically tune Rx sensitivity (BBP register 17) based on average RSSI and 2617 * false CCA count. This function is called periodically (every seconds) when 2618 * in the RUN state. Values taken from the reference driver. 2619 */ 2620static void 2621rt2661_rx_tune(struct rt2661_softc *sc) 2622{ 2623 uint8_t bbp17; 2624 uint16_t cca; 2625 int lo, hi, dbm; 2626 2627 /* 2628 * Tuning range depends on operating band and on the presence of an 2629 * external low-noise amplifier. 2630 */ 2631 lo = 0x20; 2632 if (IEEE80211_IS_CHAN_5GHZ(sc->sc_curchan)) 2633 lo += 0x08; 2634 if ((IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan) && sc->ext_2ghz_lna) || 2635 (IEEE80211_IS_CHAN_5GHZ(sc->sc_curchan) && sc->ext_5ghz_lna)) 2636 lo += 0x10; 2637 hi = lo + 0x20; 2638 2639 /* retrieve false CCA count since last call (clear on read) */ 2640 cca = RAL_READ(sc, RT2661_STA_CSR1) & 0xffff; 2641 2642 if (dbm >= -35) { 2643 bbp17 = 0x60; 2644 } else if (dbm >= -58) { 2645 bbp17 = hi; 2646 } else if (dbm >= -66) { 2647 bbp17 = lo + 0x10; 2648 } else if (dbm >= -74) { 2649 bbp17 = lo + 0x08; 2650 } else { 2651 /* RSSI < -74dBm, tune using false CCA count */ 2652 2653 bbp17 = sc->bbp17; /* current value */ 2654 2655 hi -= 2 * (-74 - dbm); 2656 if (hi < lo) 2657 hi = lo; 2658 2659 if (bbp17 > hi) { 2660 bbp17 = hi; 2661 2662 } else if (cca > 512) { 2663 if (++bbp17 > hi) 2664 bbp17 = hi; 2665 } else if (cca < 100) { 2666 if (--bbp17 < lo) 2667 bbp17 = lo; 2668 } 2669 } 2670 2671 if (bbp17 != sc->bbp17) { 2672 rt2661_bbp_write(sc, 17, bbp17); 2673 sc->bbp17 = bbp17; 2674 } 2675} 2676 2677/* 2678 * Enter/Leave radar detection mode. 2679 * This is for 802.11h additional regulatory domains. 2680 */ 2681static void 2682rt2661_radar_start(struct rt2661_softc *sc) 2683{ 2684 uint32_t tmp; 2685 2686 /* disable Rx */ 2687 tmp = RAL_READ(sc, RT2661_TXRX_CSR0); 2688 RAL_WRITE(sc, RT2661_TXRX_CSR0, tmp | RT2661_DISABLE_RX); 2689 2690 rt2661_bbp_write(sc, 82, 0x20); 2691 rt2661_bbp_write(sc, 83, 0x00); 2692 rt2661_bbp_write(sc, 84, 0x40); 2693 2694 /* save current BBP registers values */ 2695 sc->bbp18 = rt2661_bbp_read(sc, 18); 2696 sc->bbp21 = rt2661_bbp_read(sc, 21); 2697 sc->bbp22 = rt2661_bbp_read(sc, 22); 2698 sc->bbp16 = rt2661_bbp_read(sc, 16); 2699 sc->bbp17 = rt2661_bbp_read(sc, 17); 2700 sc->bbp64 = rt2661_bbp_read(sc, 64); 2701 2702 rt2661_bbp_write(sc, 18, 0xff); 2703 rt2661_bbp_write(sc, 21, 0x3f); 2704 rt2661_bbp_write(sc, 22, 0x3f); 2705 rt2661_bbp_write(sc, 16, 0xbd); 2706 rt2661_bbp_write(sc, 17, sc->ext_5ghz_lna ? 0x44 : 0x34); 2707 rt2661_bbp_write(sc, 64, 0x21); 2708 2709 /* restore Rx filter */ 2710 RAL_WRITE(sc, RT2661_TXRX_CSR0, tmp); 2711} 2712 2713static int 2714rt2661_radar_stop(struct rt2661_softc *sc) 2715{ 2716 uint8_t bbp66; 2717 2718 /* read radar detection result */ 2719 bbp66 = rt2661_bbp_read(sc, 66); 2720 2721 /* restore BBP registers values */ 2722 rt2661_bbp_write(sc, 16, sc->bbp16); 2723 rt2661_bbp_write(sc, 17, sc->bbp17); 2724 rt2661_bbp_write(sc, 18, sc->bbp18); 2725 rt2661_bbp_write(sc, 21, sc->bbp21); 2726 rt2661_bbp_write(sc, 22, sc->bbp22); 2727 rt2661_bbp_write(sc, 64, sc->bbp64); 2728 2729 return bbp66 == 1; 2730} 2731#endif 2732 2733static int 2734rt2661_prepare_beacon(struct rt2661_softc *sc, struct ieee80211vap *vap) 2735{ 2736 struct ieee80211com *ic = vap->iv_ic; 2737 struct ieee80211_beacon_offsets bo; 2738 struct rt2661_tx_desc desc; 2739 struct mbuf *m0; 2740 int rate; 2741 2742 m0 = ieee80211_beacon_alloc(vap->iv_bss, &bo); 2743 if (m0 == NULL) { 2744 device_printf(sc->sc_dev, "could not allocate beacon frame\n"); 2745 return ENOBUFS; 2746 } 2747 2748 /* send beacons at the lowest available rate */ 2749 rate = IEEE80211_IS_CHAN_5GHZ(ic->ic_bsschan) ? 12 : 2; 2750 2751 rt2661_setup_tx_desc(sc, &desc, RT2661_TX_TIMESTAMP, RT2661_TX_HWSEQ, 2752 m0->m_pkthdr.len, rate, NULL, 0, RT2661_QID_MGT); 2753 2754 /* copy the first 24 bytes of Tx descriptor into NIC memory */ 2755 RAL_WRITE_REGION_1(sc, RT2661_HW_BEACON_BASE0, (uint8_t *)&desc, 24); 2756 2757 /* copy beacon header and payload into NIC memory */ 2758 RAL_WRITE_REGION_1(sc, RT2661_HW_BEACON_BASE0 + 24, 2759 mtod(m0, uint8_t *), m0->m_pkthdr.len); 2760 2761 m_freem(m0); 2762 2763 return 0; 2764} 2765 2766/* 2767 * Enable TSF synchronization and tell h/w to start sending beacons for IBSS 2768 * and HostAP operating modes. 2769 */ 2770static void 2771rt2661_enable_tsf_sync(struct rt2661_softc *sc) 2772{ 2773 struct ifnet *ifp = sc->sc_ifp; 2774 struct ieee80211com *ic = ifp->if_l2com; 2775 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); 2776 uint32_t tmp; 2777 2778 if (vap->iv_opmode != IEEE80211_M_STA) { 2779 /* 2780 * Change default 16ms TBTT adjustment to 8ms. 2781 * Must be done before enabling beacon generation. 2782 */ 2783 RAL_WRITE(sc, RT2661_TXRX_CSR10, 1 << 12 | 8); 2784 } 2785 2786 tmp = RAL_READ(sc, RT2661_TXRX_CSR9) & 0xff000000; 2787 2788 /* set beacon interval (in 1/16ms unit) */ 2789 tmp |= vap->iv_bss->ni_intval * 16; 2790 2791 tmp |= RT2661_TSF_TICKING | RT2661_ENABLE_TBTT; 2792 if (vap->iv_opmode == IEEE80211_M_STA) 2793 tmp |= RT2661_TSF_MODE(1); 2794 else 2795 tmp |= RT2661_TSF_MODE(2) | RT2661_GENERATE_BEACON; 2796 2797 RAL_WRITE(sc, RT2661_TXRX_CSR9, tmp); 2798} 2799 2800/* 2801 * Retrieve the "Received Signal Strength Indicator" from the raw values 2802 * contained in Rx descriptors. The computation depends on which band the 2803 * frame was received. Correction values taken from the reference driver. 2804 */ 2805static int 2806rt2661_get_rssi(struct rt2661_softc *sc, uint8_t raw) 2807{ 2808 int lna, agc, rssi; 2809 2810 lna = (raw >> 5) & 0x3; 2811 agc = raw & 0x1f; 2812 2813 if (lna == 0) { 2814 /* 2815 * No mapping available. 2816 * 2817 * NB: Since RSSI is relative to noise floor, -1 is 2818 * adequate for caller to know error happened. 2819 */ 2820 return -1; 2821 } 2822 2823 rssi = (2 * agc) - RT2661_NOISE_FLOOR; 2824 2825 if (IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan)) { 2826 rssi += sc->rssi_2ghz_corr; 2827 2828 if (lna == 1) 2829 rssi -= 64; 2830 else if (lna == 2) 2831 rssi -= 74; 2832 else if (lna == 3) 2833 rssi -= 90; 2834 } else { 2835 rssi += sc->rssi_5ghz_corr; 2836 2837 if (lna == 1) 2838 rssi -= 64; 2839 else if (lna == 2) 2840 rssi -= 86; 2841 else if (lna == 3) 2842 rssi -= 100; 2843 } 2844 return rssi; 2845} 2846 2847static void 2848rt2661_scan_start(struct ieee80211com *ic) 2849{ 2850 struct ifnet *ifp = ic->ic_ifp; 2851 struct rt2661_softc *sc = ifp->if_softc; 2852 uint32_t tmp; 2853 2854 /* abort TSF synchronization */ 2855 tmp = RAL_READ(sc, RT2661_TXRX_CSR9); 2856 RAL_WRITE(sc, RT2661_TXRX_CSR9, tmp & ~0xffffff); 2857 rt2661_set_bssid(sc, ifp->if_broadcastaddr); 2858} 2859 2860static void 2861rt2661_scan_end(struct ieee80211com *ic) 2862{ 2863 struct ifnet *ifp = ic->ic_ifp; 2864 struct rt2661_softc *sc = ifp->if_softc; 2865 struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); 2866 2867 rt2661_enable_tsf_sync(sc); 2868 /* XXX keep local copy */ 2869 rt2661_set_bssid(sc, vap->iv_bss->ni_bssid); 2870} 2871 2872static void 2873rt2661_set_channel(struct ieee80211com *ic) 2874{ 2875 struct ifnet *ifp = ic->ic_ifp; 2876 struct rt2661_softc *sc = ifp->if_softc; 2877 2878 RAL_LOCK(sc); 2879 rt2661_set_chan(sc, ic->ic_curchan); 2880 2881 sc->sc_txtap.wt_chan_freq = htole16(ic->ic_curchan->ic_freq); 2882 sc->sc_txtap.wt_chan_flags = htole16(ic->ic_curchan->ic_flags); 2883 sc->sc_rxtap.wr_chan_freq = htole16(ic->ic_curchan->ic_freq); 2884 sc->sc_rxtap.wr_chan_flags = htole16(ic->ic_curchan->ic_flags); 2885 RAL_UNLOCK(sc); 2886 2887} 2888