rt2560.c revision 159180
1170530Ssam/* $FreeBSD: head/sys/dev/ral/rt2560.c 159180 2006-06-02 19:59:33Z csjp $ */ 2178354Ssam 3170530Ssam/*- 4170530Ssam * Copyright (c) 2005, 2006 5170530Ssam * Damien Bergamini <damien.bergamini@free.fr> 6170530Ssam * 7170530Ssam * Permission to use, copy, modify, and distribute this software for any 8170530Ssam * purpose with or without fee is hereby granted, provided that the above 9170530Ssam * copyright notice and this permission notice appear in all copies. 10170530Ssam * 11170530Ssam * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12170530Ssam * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13170530Ssam * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14170530Ssam * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15170530Ssam * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16170530Ssam * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17170530Ssam * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18170530Ssam */ 19170530Ssam 20170530Ssam#include <sys/cdefs.h> 21170530Ssam__FBSDID("$FreeBSD: head/sys/dev/ral/rt2560.c 159180 2006-06-02 19:59:33Z csjp $"); 22170530Ssam 23170530Ssam/*- 24170530Ssam * Ralink Technology RT2560 chipset driver 25170530Ssam * http://www.ralinktech.com/ 26170530Ssam */ 27170530Ssam 28170530Ssam#include <sys/param.h> 29170530Ssam#include <sys/sysctl.h> 30170530Ssam#include <sys/sockio.h> 31170530Ssam#include <sys/mbuf.h> 32170530Ssam#include <sys/kernel.h> 33170530Ssam#include <sys/socket.h> 34170530Ssam#include <sys/systm.h> 35170530Ssam#include <sys/malloc.h> 36178354Ssam#include <sys/module.h> 37170530Ssam#include <sys/bus.h> 38170530Ssam#include <sys/endian.h> 39170530Ssam 40170530Ssam#include <machine/bus.h> 41170530Ssam#include <machine/resource.h> 42170530Ssam#include <sys/rman.h> 43170530Ssam 44170530Ssam#include <net/bpf.h> 45170530Ssam#include <net/if.h> 46170530Ssam#include <net/if_arp.h> 47170530Ssam#include <net/ethernet.h> 48170530Ssam#include <net/if_dl.h> 49170530Ssam#include <net/if_media.h> 50178354Ssam#include <net/if_types.h> 51170530Ssam 52170530Ssam#include <net80211/ieee80211_var.h> 53170530Ssam#include <net80211/ieee80211_radiotap.h> 54170530Ssam 55170530Ssam#include <netinet/in.h> 56178354Ssam#include <netinet/in_systm.h> 57178354Ssam#include <netinet/in_var.h> 58178354Ssam#include <netinet/ip.h> 59178354Ssam#include <netinet/if_ether.h> 60178354Ssam 61178354Ssam#include <dev/ral/if_ralrate.h> 62178354Ssam#include <dev/ral/rt2560reg.h> 63178354Ssam#include <dev/ral/rt2560var.h> 64178354Ssam 65178354Ssam#ifdef RAL_DEBUG 66178354Ssam#define DPRINTF(x) do { if (ral_debug > 0) printf x; } while (0) 67178354Ssam#define DPRINTFN(n, x) do { if (ral_debug >= (n)) printf x; } while (0) 68178354Ssamextern int ral_debug; 69178354Ssam#else 70178354Ssam#define DPRINTF(x) 71178354Ssam#define DPRINTFN(n, x) 72178354Ssam#endif 73170530Ssam 74170530Ssamstatic void rt2560_dma_map_addr(void *, bus_dma_segment_t *, int, 75170530Ssam int); 76170530Ssamstatic int rt2560_alloc_tx_ring(struct rt2560_softc *, 77170530Ssam struct rt2560_tx_ring *, int); 78170530Ssamstatic void rt2560_reset_tx_ring(struct rt2560_softc *, 79170530Ssam struct rt2560_tx_ring *); 80170530Ssamstatic void rt2560_free_tx_ring(struct rt2560_softc *, 81173273Ssam struct rt2560_tx_ring *); 82173273Ssamstatic int rt2560_alloc_rx_ring(struct rt2560_softc *, 83173273Ssam struct rt2560_rx_ring *, int); 84173273Ssamstatic void rt2560_reset_rx_ring(struct rt2560_softc *, 85173273Ssam struct rt2560_rx_ring *); 86178354Ssamstatic void rt2560_free_rx_ring(struct rt2560_softc *, 87178354Ssam struct rt2560_rx_ring *); 88178354Ssamstatic struct ieee80211_node *rt2560_node_alloc( 89173273Ssam struct ieee80211_node_table *); 90178354Ssamstatic int rt2560_media_change(struct ifnet *); 91178354Ssamstatic void rt2560_next_scan(void *); 92178354Ssamstatic void rt2560_iter_func(void *, struct ieee80211_node *); 93178354Ssamstatic void rt2560_update_rssadapt(void *); 94178354Ssamstatic int rt2560_newstate(struct ieee80211com *, 95178354Ssam enum ieee80211_state, int); 96178354Ssamstatic uint16_t rt2560_eeprom_read(struct rt2560_softc *, uint8_t); 97178354Ssamstatic void rt2560_encryption_intr(struct rt2560_softc *); 98178354Ssamstatic void rt2560_tx_intr(struct rt2560_softc *); 99178354Ssamstatic void rt2560_prio_intr(struct rt2560_softc *); 100178354Ssamstatic void rt2560_decryption_intr(struct rt2560_softc *); 101178354Ssamstatic void rt2560_rx_intr(struct rt2560_softc *); 102178354Ssamstatic void rt2560_beacon_expire(struct rt2560_softc *); 103170530Ssamstatic void rt2560_wakeup_expire(struct rt2560_softc *); 104178354Ssamstatic uint8_t rt2560_rxrate(struct rt2560_rx_desc *); 105178354Ssamstatic int rt2560_ack_rate(struct ieee80211com *, int); 106170530Ssamstatic uint16_t rt2560_txtime(int, int, uint32_t); 107170530Ssamstatic uint8_t rt2560_plcp_signal(int); 108170530Ssamstatic void rt2560_setup_tx_desc(struct rt2560_softc *, 109170530Ssam struct rt2560_tx_desc *, uint32_t, int, int, int, 110170530Ssam bus_addr_t); 111170530Ssamstatic int rt2560_tx_bcn(struct rt2560_softc *, struct mbuf *, 112170530Ssam struct ieee80211_node *); 113170530Ssamstatic int rt2560_tx_mgt(struct rt2560_softc *, struct mbuf *, 114170530Ssam struct ieee80211_node *); 115170530Ssamstatic struct mbuf *rt2560_get_rts(struct rt2560_softc *, 116170530Ssam struct ieee80211_frame *, uint16_t); 117170530Ssamstatic int rt2560_tx_data(struct rt2560_softc *, struct mbuf *, 118170530Ssam struct ieee80211_node *); 119170530Ssamstatic void rt2560_start(struct ifnet *); 120170530Ssamstatic void rt2560_watchdog(struct ifnet *); 121170530Ssamstatic int rt2560_reset(struct ifnet *); 122170530Ssamstatic int rt2560_ioctl(struct ifnet *, u_long, caddr_t); 123178354Ssamstatic void rt2560_bbp_write(struct rt2560_softc *, uint8_t, 124170530Ssam uint8_t); 125170530Ssamstatic uint8_t rt2560_bbp_read(struct rt2560_softc *, uint8_t); 126170530Ssamstatic void rt2560_rf_write(struct rt2560_softc *, uint8_t, 127170530Ssam uint32_t); 128173273Ssamstatic void rt2560_set_chan(struct rt2560_softc *, 129173273Ssam struct ieee80211_channel *); 130178354Ssam#if 0 131173273Ssamstatic void rt2560_disable_rf_tune(struct rt2560_softc *); 132178354Ssam#endif 133178354Ssamstatic void rt2560_enable_tsf_sync(struct rt2560_softc *); 134178354Ssamstatic void rt2560_update_plcp(struct rt2560_softc *); 135178354Ssamstatic void rt2560_update_slot(struct ifnet *); 136173273Ssamstatic void rt2560_set_basicrates(struct rt2560_softc *); 137178354Ssamstatic void rt2560_update_led(struct rt2560_softc *, int, int); 138178354Ssamstatic void rt2560_set_bssid(struct rt2560_softc *, uint8_t *); 139178354Ssamstatic void rt2560_set_macaddr(struct rt2560_softc *, uint8_t *); 140178354Ssamstatic void rt2560_get_macaddr(struct rt2560_softc *, uint8_t *); 141178354Ssamstatic void rt2560_update_promisc(struct rt2560_softc *); 142178354Ssamstatic const char *rt2560_get_rf(int); 143178354Ssamstatic void rt2560_read_eeprom(struct rt2560_softc *); 144178354Ssamstatic int rt2560_bbp_init(struct rt2560_softc *); 145178354Ssamstatic void rt2560_set_txantenna(struct rt2560_softc *, int); 146178354Ssamstatic void rt2560_set_rxantenna(struct rt2560_softc *, int); 147178354Ssamstatic void rt2560_init(void *); 148178354Ssamstatic void rt2560_stop(void *); 149178354Ssam 150178354Ssam/* 151178354Ssam * Supported rates for 802.11a/b/g modes (in 500Kbps unit). 152178354Ssam */ 153170530Ssamstatic const struct ieee80211_rateset rt2560_rateset_11a = 154173273Ssam { 8, { 12, 18, 24, 36, 48, 72, 96, 108 } }; 155173273Ssam 156170530Ssamstatic const struct ieee80211_rateset rt2560_rateset_11b = 157170530Ssam { 4, { 2, 4, 11, 22 } }; 158178354Ssam 159178354Ssamstatic const struct ieee80211_rateset rt2560_rateset_11g = 160178354Ssam { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } }; 161178354Ssam 162178354Ssamstatic const struct { 163173273Ssam uint32_t reg; 164178354Ssam uint32_t val; 165178354Ssam} rt2560_def_mac[] = { 166178354Ssam RT2560_DEF_MAC 167178354Ssam}; 168170530Ssam 169170530Ssamstatic const struct { 170178354Ssam uint8_t reg; 171178354Ssam uint8_t val; 172178354Ssam} rt2560_def_bbp[] = { 173178354Ssam RT2560_DEF_BBP 174178354Ssam}; 175178354Ssam 176170530Ssamstatic const uint32_t rt2560_rf2522_r2[] = RT2560_RF2522_R2; 177178354Ssamstatic const uint32_t rt2560_rf2523_r2[] = RT2560_RF2523_R2; 178178354Ssamstatic const uint32_t rt2560_rf2524_r2[] = RT2560_RF2524_R2; 179178354Ssamstatic const uint32_t rt2560_rf2525_r2[] = RT2560_RF2525_R2; 180170530Ssamstatic const uint32_t rt2560_rf2525_hi_r2[] = RT2560_RF2525_HI_R2; 181170530Ssamstatic const uint32_t rt2560_rf2525e_r2[] = RT2560_RF2525E_R2; 182170530Ssamstatic const uint32_t rt2560_rf2526_r2[] = RT2560_RF2526_R2; 183178354Ssamstatic const uint32_t rt2560_rf2526_hi_r2[] = RT2560_RF2526_HI_R2; 184170530Ssam 185170530Ssamstatic const struct { 186170530Ssam uint8_t chan; 187170530Ssam uint32_t r1, r2, r4; 188170530Ssam} rt2560_rf5222[] = { 189170530Ssam RT2560_RF5222 190170530Ssam}; 191170530Ssam 192170530Ssamint 193170530Ssamrt2560_attach(device_t dev, int id) 194170530Ssam{ 195170530Ssam struct rt2560_softc *sc = device_get_softc(dev); 196172226Ssam struct ieee80211com *ic = &sc->sc_ic; 197172226Ssam struct ifnet *ifp; 198170530Ssam int error, i; 199170530Ssam 200178354Ssam sc->sc_dev = dev; 201170530Ssam 202170530Ssam mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, 203170530Ssam MTX_DEF | MTX_RECURSE); 204170530Ssam 205170530Ssam callout_init(&sc->scan_ch, debug_mpsafenet ? CALLOUT_MPSAFE : 0); 206170530Ssam callout_init(&sc->rssadapt_ch, CALLOUT_MPSAFE); 207170530Ssam 208170530Ssam /* retrieve RT2560 rev. no */ 209170530Ssam sc->asic_rev = RAL_READ(sc, RT2560_CSR0); 210170530Ssam 211170530Ssam /* retrieve MAC address */ 212170530Ssam rt2560_get_macaddr(sc, ic->ic_myaddr); 213170530Ssam 214170530Ssam /* retrieve RF rev. no and various other things from EEPROM */ 215170530Ssam rt2560_read_eeprom(sc); 216170530Ssam 217170530Ssam device_printf(dev, "MAC/BBP RT2560 (rev 0x%02x), RF %s\n", 218170530Ssam sc->asic_rev, rt2560_get_rf(sc->rf_rev)); 219170530Ssam 220173273Ssam /* 221170530Ssam * Allocate Tx and Rx rings. 222170530Ssam */ 223170530Ssam error = rt2560_alloc_tx_ring(sc, &sc->txq, RT2560_TX_RING_COUNT); 224170530Ssam if (error != 0) { 225170530Ssam device_printf(sc->sc_dev, "could not allocate Tx ring\n"); 226170530Ssam goto fail1; 227170530Ssam } 228170530Ssam 229170530Ssam error = rt2560_alloc_tx_ring(sc, &sc->atimq, RT2560_ATIM_RING_COUNT); 230170530Ssam if (error != 0) { 231170530Ssam device_printf(sc->sc_dev, "could not allocate ATIM ring\n"); 232170530Ssam goto fail2; 233170530Ssam } 234170530Ssam 235178354Ssam error = rt2560_alloc_tx_ring(sc, &sc->prioq, RT2560_PRIO_RING_COUNT); 236173462Ssam if (error != 0) { 237170530Ssam device_printf(sc->sc_dev, "could not allocate Prio ring\n"); 238170530Ssam goto fail3; 239170530Ssam } 240170530Ssam 241170530Ssam error = rt2560_alloc_tx_ring(sc, &sc->bcnq, RT2560_BEACON_RING_COUNT); 242178354Ssam if (error != 0) { 243170530Ssam device_printf(sc->sc_dev, "could not allocate Beacon ring\n"); 244170530Ssam goto fail4; 245170530Ssam } 246170530Ssam 247170530Ssam error = rt2560_alloc_rx_ring(sc, &sc->rxq, RT2560_RX_RING_COUNT); 248170530Ssam if (error != 0) { 249170530Ssam device_printf(sc->sc_dev, "could not allocate Rx ring\n"); 250170530Ssam goto fail5; 251170530Ssam } 252170530Ssam 253178354Ssam ifp = sc->sc_ifp = if_alloc(IFT_ETHER); 254173462Ssam if (ifp == NULL) { 255178354Ssam device_printf(sc->sc_dev, "can not if_alloc()\n"); 256170530Ssam goto fail6; 257170530Ssam } 258173462Ssam 259170530Ssam ifp->if_softc = sc; 260170530Ssam if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 261170530Ssam ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 262178354Ssam ifp->if_init = rt2560_init; 263170530Ssam ifp->if_ioctl = rt2560_ioctl; 264170530Ssam ifp->if_start = rt2560_start; 265178354Ssam ifp->if_watchdog = rt2560_watchdog; 266170530Ssam IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); 267170530Ssam ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; 268170530Ssam IFQ_SET_READY(&ifp->if_snd); 269178354Ssam 270170530Ssam ic->ic_ifp = ifp; 271170530Ssam ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ 272170530Ssam ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ 273170530Ssam ic->ic_state = IEEE80211_S_INIT; 274170530Ssam 275170530Ssam /* set device capabilities */ 276170530Ssam ic->ic_caps = 277170530Ssam IEEE80211_C_IBSS | /* IBSS mode supported */ 278170530Ssam IEEE80211_C_MONITOR | /* monitor mode supported */ 279170530Ssam IEEE80211_C_HOSTAP | /* HostAp mode supported */ 280170530Ssam IEEE80211_C_TXPMGT | /* tx power management */ 281170530Ssam IEEE80211_C_SHPREAMBLE | /* short preamble supported */ 282170530Ssam IEEE80211_C_SHSLOT | /* short slot time supported */ 283170530Ssam IEEE80211_C_WPA; /* 802.11i */ 284170530Ssam 285170530Ssam if (sc->rf_rev == RT2560_RF_5222) { 286170530Ssam /* set supported .11a rates */ 287170530Ssam ic->ic_sup_rates[IEEE80211_MODE_11A] = rt2560_rateset_11a; 288170530Ssam 289170530Ssam /* set supported .11a channels */ 290170530Ssam for (i = 36; i <= 64; i += 4) { 291170530Ssam ic->ic_channels[i].ic_freq = 292170530Ssam ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ); 293170530Ssam ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A; 294170530Ssam } 295170530Ssam for (i = 100; i <= 140; i += 4) { 296170530Ssam ic->ic_channels[i].ic_freq = 297170530Ssam ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ); 298170530Ssam ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A; 299170530Ssam } 300170530Ssam for (i = 149; i <= 161; i += 4) { 301170530Ssam ic->ic_channels[i].ic_freq = 302170530Ssam ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ); 303170530Ssam ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A; 304170530Ssam } 305170530Ssam } 306178354Ssam 307178354Ssam /* set supported .11b and .11g rates */ 308178354Ssam ic->ic_sup_rates[IEEE80211_MODE_11B] = rt2560_rateset_11b; 309178354Ssam ic->ic_sup_rates[IEEE80211_MODE_11G] = rt2560_rateset_11g; 310178354Ssam 311178354Ssam /* set supported .11b and .11g channels (1 through 14) */ 312178354Ssam for (i = 1; i <= 14; i++) { 313178354Ssam ic->ic_channels[i].ic_freq = 314178354Ssam ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ); 315178354Ssam ic->ic_channels[i].ic_flags = 316178354Ssam IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM | 317178354Ssam IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ; 318178354Ssam } 319178354Ssam 320178354Ssam ieee80211_ifattach(ic); 321178354Ssam ic->ic_node_alloc = rt2560_node_alloc; 322178354Ssam ic->ic_updateslot = rt2560_update_slot; 323178354Ssam ic->ic_reset = rt2560_reset; 324178354Ssam /* enable s/w bmiss handling in sta mode */ 325178354Ssam ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS; 326170530Ssam 327170530Ssam /* override state transition machine */ 328170530Ssam sc->sc_newstate = ic->ic_newstate; 329170530Ssam ic->ic_newstate = rt2560_newstate; 330170530Ssam ieee80211_media_init(ic, rt2560_media_change, ieee80211_media_status); 331170530Ssam 332178354Ssam bpfattach2(ifp, DLT_IEEE802_11_RADIO, 333170530Ssam sizeof (struct ieee80211_frame) + 64, &sc->sc_drvbpf); 334170530Ssam 335170530Ssam sc->sc_rxtap_len = sizeof sc->sc_rxtapu; 336170530Ssam sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len); 337170530Ssam sc->sc_rxtap.wr_ihdr.it_present = htole32(RT2560_RX_RADIOTAP_PRESENT); 338170530Ssam 339170530Ssam sc->sc_txtap_len = sizeof sc->sc_txtapu; 340170530Ssam sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len); 341170530Ssam sc->sc_txtap.wt_ihdr.it_present = htole32(RT2560_TX_RADIOTAP_PRESENT); 342170530Ssam 343170530Ssam /* 344170530Ssam * Add a few sysctl knobs. 345170530Ssam */ 346178354Ssam sc->dwelltime = 200; 347170530Ssam 348170530Ssam SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), 349170530Ssam SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 350170530Ssam "txantenna", CTLFLAG_RW, &sc->tx_ant, 0, "tx antenna (0=auto)"); 351170530Ssam 352170530Ssam SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), 353170530Ssam SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 354170530Ssam "rxantenna", CTLFLAG_RW, &sc->rx_ant, 0, "rx antenna (0=auto)"); 355170530Ssam 356170530Ssam SYSCTL_ADD_INT(device_get_sysctl_ctx(dev), 357170530Ssam SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "dwell", 358170530Ssam CTLFLAG_RW, &sc->dwelltime, 0, 359170530Ssam "channel dwell time (ms) for AP/station scanning"); 360178354Ssam 361170530Ssam if (bootverbose) 362170530Ssam ieee80211_announce(ic); 363170530Ssam 364170530Ssam return 0; 365170530Ssam 366170530Ssamfail6: rt2560_free_rx_ring(sc, &sc->rxq); 367170530Ssamfail5: rt2560_free_tx_ring(sc, &sc->bcnq); 368170530Ssamfail4: rt2560_free_tx_ring(sc, &sc->prioq); 369170530Ssamfail3: rt2560_free_tx_ring(sc, &sc->atimq); 370170530Ssamfail2: rt2560_free_tx_ring(sc, &sc->txq); 371170530Ssamfail1: mtx_destroy(&sc->sc_mtx); 372170530Ssam 373170530Ssam return ENXIO; 374170530Ssam} 375170530Ssam 376170530Ssamint 377170530Ssamrt2560_detach(void *xsc) 378170530Ssam{ 379170530Ssam struct rt2560_softc *sc = xsc; 380170530Ssam struct ieee80211com *ic = &sc->sc_ic; 381170530Ssam struct ifnet *ifp = ic->ic_ifp; 382170530Ssam 383170530Ssam rt2560_stop(sc); 384170530Ssam callout_stop(&sc->scan_ch); 385170530Ssam callout_stop(&sc->rssadapt_ch); 386170530Ssam 387170530Ssam bpfdetach(ifp); 388170530Ssam ieee80211_ifdetach(ic); 389170530Ssam 390178354Ssam rt2560_free_tx_ring(sc, &sc->txq); 391170530Ssam rt2560_free_tx_ring(sc, &sc->atimq); 392173273Ssam rt2560_free_tx_ring(sc, &sc->prioq); 393173273Ssam rt2560_free_tx_ring(sc, &sc->bcnq); 394173273Ssam rt2560_free_rx_ring(sc, &sc->rxq); 395173273Ssam 396173273Ssam if_free(ifp); 397178354Ssam 398170530Ssam mtx_destroy(&sc->sc_mtx); 399170530Ssam 400173273Ssam return 0; 401170530Ssam} 402173273Ssam 403170530Ssamvoid 404170530Ssamrt2560_shutdown(void *xsc) 405173273Ssam{ 406170530Ssam struct rt2560_softc *sc = xsc; 407178354Ssam 408170530Ssam rt2560_stop(sc); 409170530Ssam} 410170530Ssam 411173273Ssamvoid 412170530Ssamrt2560_suspend(void *xsc) 413170530Ssam{ 414170530Ssam struct rt2560_softc *sc = xsc; 415170530Ssam 416170530Ssam rt2560_stop(sc); 417173273Ssam} 418178354Ssam 419173273Ssamvoid 420170530Ssamrt2560_resume(void *xsc) 421173273Ssam{ 422170530Ssam struct rt2560_softc *sc = xsc; 423170530Ssam struct ifnet *ifp = sc->sc_ic.ic_ifp; 424170530Ssam 425173273Ssam if (ifp->if_flags & IFF_UP) { 426170530Ssam ifp->if_init(ifp->if_softc); 427170530Ssam if (ifp->if_drv_flags & IFF_DRV_RUNNING) 428173273Ssam ifp->if_start(ifp); 429173273Ssam } 430173273Ssam} 431173273Ssam 432173273Ssamstatic void 433173273Ssamrt2560_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error) 434173273Ssam{ 435173273Ssam if (error != 0) 436178354Ssam return; 437173273Ssam 438173273Ssam KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); 439173273Ssam 440173273Ssam *(bus_addr_t *)arg = segs[0].ds_addr; 441173273Ssam} 442173273Ssam 443173273Ssamstatic int 444173273Ssamrt2560_alloc_tx_ring(struct rt2560_softc *sc, struct rt2560_tx_ring *ring, 445173273Ssam int count) 446173273Ssam{ 447173273Ssam int i, error; 448173273Ssam 449173273Ssam ring->count = count; 450173273Ssam ring->queued = 0; 451173273Ssam ring->cur = ring->next = 0; 452173273Ssam ring->cur_encrypt = ring->next_encrypt = 0; 453173273Ssam 454173273Ssam error = bus_dma_tag_create(NULL, 4, 0, BUS_SPACE_MAXADDR_32BIT, 455178354Ssam BUS_SPACE_MAXADDR, NULL, NULL, count * RT2560_TX_DESC_SIZE, 1, 456173273Ssam count * RT2560_TX_DESC_SIZE, 0, NULL, NULL, &ring->desc_dmat); 457173273Ssam if (error != 0) { 458173273Ssam device_printf(sc->sc_dev, "could not create desc DMA tag\n"); 459173273Ssam goto fail; 460173273Ssam } 461173273Ssam 462173273Ssam error = bus_dmamem_alloc(ring->desc_dmat, (void **)&ring->desc, 463173273Ssam BUS_DMA_NOWAIT | BUS_DMA_ZERO, &ring->desc_map); 464173273Ssam if (error != 0) { 465173273Ssam device_printf(sc->sc_dev, "could not allocate DMA memory\n"); 466173273Ssam goto fail; 467173273Ssam } 468173273Ssam 469173273Ssam error = bus_dmamap_load(ring->desc_dmat, ring->desc_map, ring->desc, 470178354Ssam count * RT2560_TX_DESC_SIZE, rt2560_dma_map_addr, &ring->physaddr, 471178354Ssam 0); 472178354Ssam if (error != 0) { 473178354Ssam device_printf(sc->sc_dev, "could not load desc DMA map\n"); 474173273Ssam goto fail; 475173273Ssam } 476173273Ssam 477173273Ssam ring->data = malloc(count * sizeof (struct rt2560_tx_data), M_DEVBUF, 478173273Ssam M_NOWAIT | M_ZERO); 479173273Ssam if (ring->data == NULL) { 480173273Ssam device_printf(sc->sc_dev, "could not allocate soft data\n"); 481173273Ssam error = ENOMEM; 482173273Ssam goto fail; 483173273Ssam } 484173273Ssam 485173273Ssam error = bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT, 486173273Ssam BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, RT2560_MAX_SCATTER, 487178354Ssam MCLBYTES, 0, NULL, NULL, &ring->data_dmat); 488173273Ssam if (error != 0) { 489173273Ssam device_printf(sc->sc_dev, "could not create data DMA tag\n"); 490173273Ssam goto fail; 491173273Ssam } 492173273Ssam 493173273Ssam for (i = 0; i < count; i++) { 494173273Ssam error = bus_dmamap_create(ring->data_dmat, 0, 495173273Ssam &ring->data[i].map); 496173273Ssam if (error != 0) { 497173273Ssam device_printf(sc->sc_dev, "could not create DMA map\n"); 498173273Ssam goto fail; 499170530Ssam } 500170530Ssam } 501170530Ssam 502173273Ssam return 0; 503170530Ssam 504170530Ssamfail: rt2560_free_tx_ring(sc, ring); 505170530Ssam return error; 506170530Ssam} 507170530Ssam 508170530Ssamstatic void 509170530Ssamrt2560_reset_tx_ring(struct rt2560_softc *sc, struct rt2560_tx_ring *ring) 510170530Ssam{ 511173273Ssam struct rt2560_tx_desc *desc; 512173273Ssam struct rt2560_tx_data *data; 513178354Ssam int i; 514170530Ssam 515170530Ssam for (i = 0; i < ring->count; i++) { 516170530Ssam desc = &ring->desc[i]; 517170530Ssam data = &ring->data[i]; 518170530Ssam 519170530Ssam if (data->m != NULL) { 520170530Ssam bus_dmamap_sync(ring->data_dmat, data->map, 521170530Ssam BUS_DMASYNC_POSTWRITE); 522170530Ssam bus_dmamap_unload(ring->data_dmat, data->map); 523170530Ssam m_freem(data->m); 524170530Ssam data->m = NULL; 525170530Ssam } 526173273Ssam 527173273Ssam if (data->ni != NULL) { 528173273Ssam ieee80211_free_node(data->ni); 529173273Ssam data->ni = NULL; 530173273Ssam } 531170530Ssam 532170530Ssam desc->flags = 0; 533170530Ssam } 534170530Ssam 535170530Ssam bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_PREWRITE); 536173273Ssam 537170530Ssam ring->queued = 0; 538182827Ssam ring->cur = ring->next = 0; 539182827Ssam ring->cur_encrypt = ring->next_encrypt = 0; 540182827Ssam} 541182827Ssam 542182827Ssamstatic void 543182827Ssamrt2560_free_tx_ring(struct rt2560_softc *sc, struct rt2560_tx_ring *ring) 544182827Ssam{ 545182827Ssam struct rt2560_tx_data *data; 546182827Ssam int i; 547182827Ssam 548182827Ssam if (ring->desc != NULL) { 549182827Ssam bus_dmamap_sync(ring->desc_dmat, ring->desc_map, 550182827Ssam BUS_DMASYNC_POSTWRITE); 551182827Ssam bus_dmamap_unload(ring->desc_dmat, ring->desc_map); 552182827Ssam bus_dmamem_free(ring->desc_dmat, ring->desc, ring->desc_map); 553173273Ssam } 554173273Ssam 555170530Ssam if (ring->desc_dmat != NULL) 556170530Ssam bus_dma_tag_destroy(ring->desc_dmat); 557170530Ssam 558170530Ssam if (ring->data != NULL) { 559170530Ssam for (i = 0; i < ring->count; i++) { 560170530Ssam data = &ring->data[i]; 561170530Ssam 562170530Ssam if (data->m != NULL) { 563170530Ssam bus_dmamap_sync(ring->data_dmat, data->map, 564170530Ssam BUS_DMASYNC_POSTWRITE); 565170530Ssam bus_dmamap_unload(ring->data_dmat, data->map); 566173273Ssam m_freem(data->m); 567170530Ssam } 568170530Ssam 569170530Ssam if (data->ni != NULL) 570170530Ssam ieee80211_free_node(data->ni); 571170530Ssam 572170530Ssam if (data->map != NULL) 573173273Ssam bus_dmamap_destroy(ring->data_dmat, data->map); 574170530Ssam } 575170530Ssam 576170530Ssam free(ring->data, M_DEVBUF); 577173273Ssam } 578170530Ssam 579170530Ssam if (ring->data_dmat != NULL) 580170530Ssam bus_dma_tag_destroy(ring->data_dmat); 581173273Ssam} 582170530Ssam 583173273Ssamstatic int 584173273Ssamrt2560_alloc_rx_ring(struct rt2560_softc *sc, struct rt2560_rx_ring *ring, 585173273Ssam int count) 586173273Ssam{ 587173273Ssam struct rt2560_rx_desc *desc; 588173273Ssam struct rt2560_rx_data *data; 589173273Ssam bus_addr_t physaddr; 590173273Ssam int i, error; 591173273Ssam 592173273Ssam ring->count = count; 593173273Ssam ring->cur = ring->next = 0; 594173273Ssam ring->cur_decrypt = 0; 595173273Ssam 596173273Ssam error = bus_dma_tag_create(NULL, 4, 0, BUS_SPACE_MAXADDR_32BIT, 597170530Ssam BUS_SPACE_MAXADDR, NULL, NULL, count * RT2560_RX_DESC_SIZE, 1, 598173273Ssam count * RT2560_RX_DESC_SIZE, 0, NULL, NULL, &ring->desc_dmat); 599173273Ssam if (error != 0) { 600173273Ssam device_printf(sc->sc_dev, "could not create desc DMA tag\n"); 601173273Ssam goto fail; 602173273Ssam } 603170530Ssam 604173273Ssam error = bus_dmamem_alloc(ring->desc_dmat, (void **)&ring->desc, 605173273Ssam BUS_DMA_NOWAIT | BUS_DMA_ZERO, &ring->desc_map); 606173273Ssam if (error != 0) { 607173273Ssam device_printf(sc->sc_dev, "could not allocate DMA memory\n"); 608173273Ssam goto fail; 609173273Ssam } 610173273Ssam 611173273Ssam error = bus_dmamap_load(ring->desc_dmat, ring->desc_map, ring->desc, 612178354Ssam count * RT2560_RX_DESC_SIZE, rt2560_dma_map_addr, &ring->physaddr, 613173273Ssam 0); 614173273Ssam if (error != 0) { 615173273Ssam device_printf(sc->sc_dev, "could not load desc DMA map\n"); 616173273Ssam goto fail; 617173273Ssam } 618173273Ssam 619173273Ssam ring->data = malloc(count * sizeof (struct rt2560_rx_data), M_DEVBUF, 620173273Ssam M_NOWAIT | M_ZERO); 621173273Ssam if (ring->data == NULL) { 622173273Ssam device_printf(sc->sc_dev, "could not allocate soft data\n"); 623173273Ssam error = ENOMEM; 624173273Ssam goto fail; 625173273Ssam } 626173273Ssam 627173273Ssam /* 628173273Ssam * Pre-allocate Rx buffers and populate Rx ring. 629173273Ssam */ 630173273Ssam error = bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT, 631178354Ssam BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 1, MCLBYTES, 0, NULL, 632173273Ssam NULL, &ring->data_dmat); 633178354Ssam if (error != 0) { 634173273Ssam device_printf(sc->sc_dev, "could not create data DMA tag\n"); 635173273Ssam goto fail; 636173273Ssam } 637173273Ssam 638173273Ssam for (i = 0; i < count; i++) { 639178354Ssam desc = &sc->rxq.desc[i]; 640173273Ssam data = &sc->rxq.data[i]; 641173273Ssam 642173273Ssam error = bus_dmamap_create(ring->data_dmat, 0, &data->map); 643173273Ssam if (error != 0) { 644173273Ssam device_printf(sc->sc_dev, "could not create DMA map\n"); 645173273Ssam goto fail; 646173273Ssam } 647173273Ssam 648173273Ssam data->m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 649173273Ssam if (data->m == NULL) { 650173273Ssam device_printf(sc->sc_dev, 651178354Ssam "could not allocate rx mbuf\n"); 652173273Ssam error = ENOMEM; 653170530Ssam goto fail; 654173273Ssam } 655170530Ssam 656178354Ssam error = bus_dmamap_load(ring->data_dmat, data->map, 657170530Ssam mtod(data->m, void *), MCLBYTES, rt2560_dma_map_addr, 658173273Ssam &physaddr, 0); 659173273Ssam if (error != 0) { 660173273Ssam device_printf(sc->sc_dev, 661173273Ssam "could not load rx buf DMA map"); 662173273Ssam goto fail; 663173273Ssam } 664173273Ssam 665173273Ssam desc->flags = htole32(RT2560_RX_BUSY); 666173273Ssam desc->physaddr = htole32(physaddr); 667173273Ssam } 668173273Ssam 669173273Ssam bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_PREWRITE); 670170530Ssam 671170530Ssam return 0; 672173273Ssam 673173273Ssamfail: rt2560_free_rx_ring(sc, ring); 674170530Ssam return error; 675178354Ssam} 676173273Ssam 677178354Ssamstatic void 678173273Ssamrt2560_reset_rx_ring(struct rt2560_softc *sc, struct rt2560_rx_ring *ring) 679173273Ssam{ 680173273Ssam int i; 681173273Ssam 682178354Ssam for (i = 0; i < ring->count; i++) { 683173273Ssam ring->desc[i].flags = htole32(RT2560_RX_BUSY); 684170530Ssam ring->data[i].drop = 0; 685173273Ssam } 686170530Ssam 687173273Ssam bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_PREWRITE); 688173273Ssam 689170530Ssam ring->cur = ring->next = 0; 690170530Ssam ring->cur_decrypt = 0; 691170530Ssam} 692170530Ssam 693170530Ssamstatic void 694170530Ssamrt2560_free_rx_ring(struct rt2560_softc *sc, struct rt2560_rx_ring *ring) 695173273Ssam{ 696170530Ssam struct rt2560_rx_data *data; 697170530Ssam int i; 698170530Ssam 699170530Ssam if (ring->desc != NULL) { 700178354Ssam bus_dmamap_sync(ring->desc_dmat, ring->desc_map, 701170530Ssam BUS_DMASYNC_POSTWRITE); 702170530Ssam bus_dmamap_unload(ring->desc_dmat, ring->desc_map); 703170530Ssam bus_dmamem_free(ring->desc_dmat, ring->desc, ring->desc_map); 704170530Ssam } 705170530Ssam 706173273Ssam if (ring->desc_dmat != NULL) 707173273Ssam bus_dma_tag_destroy(ring->desc_dmat); 708178354Ssam 709173273Ssam if (ring->data != NULL) { 710173273Ssam for (i = 0; i < ring->count; i++) { 711178354Ssam data = &ring->data[i]; 712173273Ssam 713173273Ssam if (data->m != NULL) { 714170530Ssam bus_dmamap_sync(ring->data_dmat, data->map, 715170530Ssam BUS_DMASYNC_POSTREAD); 716170530Ssam bus_dmamap_unload(ring->data_dmat, data->map); 717170530Ssam m_freem(data->m); 718170530Ssam } 719170530Ssam 720170530Ssam if (data->map != NULL) 721170530Ssam bus_dmamap_destroy(ring->data_dmat, data->map); 722178354Ssam } 723170530Ssam 724170530Ssam free(ring->data, M_DEVBUF); 725178354Ssam } 726170530Ssam 727170530Ssam if (ring->data_dmat != NULL) 728178354Ssam bus_dma_tag_destroy(ring->data_dmat); 729170530Ssam} 730173273Ssam 731173273Ssamstatic struct ieee80211_node * 732170530Ssamrt2560_node_alloc(struct ieee80211_node_table *nt) 733170530Ssam{ 734173273Ssam struct rt2560_node *rn; 735170530Ssam 736173273Ssam rn = malloc(sizeof (struct rt2560_node), M_80211_NODE, 737173273Ssam M_NOWAIT | M_ZERO); 738170530Ssam 739178354Ssam return (rn != NULL) ? &rn->ni : NULL; 740173273Ssam} 741170530Ssam 742173273Ssamstatic int 743173273Ssamrt2560_media_change(struct ifnet *ifp) 744178354Ssam{ 745173273Ssam struct rt2560_softc *sc = ifp->if_softc; 746173273Ssam int error; 747173273Ssam 748173273Ssam error = ieee80211_media_change(ifp); 749173273Ssam if (error != ENETRESET) 750173273Ssam return error; 751173273Ssam 752173273Ssam if ((ifp->if_flags & IFF_UP) && 753173273Ssam (ifp->if_drv_flags & IFF_DRV_RUNNING)) 754170530Ssam rt2560_init(sc); 755173273Ssam 756170530Ssam return 0; 757173273Ssam} 758173273Ssam 759170530Ssam/* 760178354Ssam * This function is called periodically (every 200ms) during scanning to 761173273Ssam * switch from one channel to another. 762173273Ssam */ 763173273Ssamstatic void 764173273Ssamrt2560_next_scan(void *arg) 765173273Ssam{ 766173273Ssam struct rt2560_softc *sc = arg; 767178354Ssam struct ieee80211com *ic = &sc->sc_ic; 768173273Ssam 769170530Ssam if (ic->ic_state == IEEE80211_S_SCAN) 770170530Ssam ieee80211_next_scan(ic); 771170530Ssam} 772170530Ssam 773170530Ssam/* 774170530Ssam * This function is called for each node present in the node station table. 775170530Ssam */ 776170530Ssamstatic void 777170530Ssamrt2560_iter_func(void *arg, struct ieee80211_node *ni) 778170530Ssam{ 779170530Ssam struct rt2560_node *rn = (struct rt2560_node *)ni; 780170530Ssam 781170530Ssam ral_rssadapt_updatestats(&rn->rssadapt); 782170530Ssam} 783173273Ssam 784173273Ssam/* 785173273Ssam * This function is called periodically (every 100ms) in RUN state to update 786173273Ssam * the rate adaptation statistics. 787173273Ssam */ 788173273Ssamstatic void 789173273Ssamrt2560_update_rssadapt(void *arg) 790173273Ssam{ 791170530Ssam struct rt2560_softc *sc = arg; 792170530Ssam struct ieee80211com *ic = &sc->sc_ic; 793170530Ssam 794170530Ssam RAL_LOCK(sc); 795173273Ssam 796170530Ssam ieee80211_iterate_nodes(&ic->ic_sta, rt2560_iter_func, arg); 797173273Ssam callout_reset(&sc->rssadapt_ch, hz / 10, rt2560_update_rssadapt, sc); 798170530Ssam 799170530Ssam RAL_UNLOCK(sc); 800170530Ssam} 801170530Ssam 802170530Ssamstatic int 803170530Ssamrt2560_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) 804170530Ssam{ 805170530Ssam struct rt2560_softc *sc = ic->ic_ifp->if_softc; 806170530Ssam enum ieee80211_state ostate; 807170530Ssam struct ieee80211_node *ni; 808170530Ssam struct mbuf *m; 809170530Ssam int error = 0; 810170530Ssam 811170530Ssam ostate = ic->ic_state; 812170530Ssam callout_stop(&sc->scan_ch); 813170530Ssam 814170530Ssam switch (nstate) { 815173273Ssam case IEEE80211_S_INIT: 816173273Ssam callout_stop(&sc->rssadapt_ch); 817173273Ssam 818173273Ssam if (ostate == IEEE80211_S_RUN) { 819173273Ssam /* abort TSF synchronization */ 820170530Ssam RAL_WRITE(sc, RT2560_CSR14, 0); 821178354Ssam 822178354Ssam /* turn association led off */ 823173273Ssam rt2560_update_led(sc, 0, 0); 824173273Ssam } 825173273Ssam break; 826173273Ssam 827170530Ssam case IEEE80211_S_SCAN: 828170530Ssam rt2560_set_chan(sc, ic->ic_curchan); 829170530Ssam callout_reset(&sc->scan_ch, (sc->dwelltime * hz) / 1000, 830170530Ssam rt2560_next_scan, sc); 831170530Ssam break; 832173273Ssam 833173273Ssam case IEEE80211_S_AUTH: 834170530Ssam rt2560_set_chan(sc, ic->ic_curchan); 835170530Ssam break; 836178354Ssam 837178354Ssam case IEEE80211_S_ASSOC: 838178354Ssam rt2560_set_chan(sc, ic->ic_curchan); 839178354Ssam break; 840178354Ssam 841178354Ssam case IEEE80211_S_RUN: 842178354Ssam rt2560_set_chan(sc, ic->ic_curchan); 843178354Ssam 844178354Ssam ni = ic->ic_bss; 845178354Ssam 846178354Ssam if (ic->ic_opmode != IEEE80211_M_MONITOR) { 847178354Ssam rt2560_update_plcp(sc); 848178354Ssam rt2560_set_basicrates(sc); 849178354Ssam rt2560_set_bssid(sc, ni->ni_bssid); 850178354Ssam } 851178354Ssam 852178354Ssam if (ic->ic_opmode == IEEE80211_M_HOSTAP || 853178354Ssam ic->ic_opmode == IEEE80211_M_IBSS) { 854178354Ssam m = ieee80211_beacon_alloc(ic, ni, &sc->sc_bo); 855178354Ssam if (m == NULL) { 856178354Ssam device_printf(sc->sc_dev, 857178354Ssam "could not allocate beacon\n"); 858178354Ssam error = ENOBUFS; 859178354Ssam break; 860178354Ssam } 861178354Ssam 862178354Ssam ieee80211_ref_node(ni); 863178354Ssam error = rt2560_tx_bcn(sc, m, ni); 864178354Ssam if (error != 0) 865178354Ssam break; 866178354Ssam } 867178354Ssam 868178354Ssam /* turn assocation led on */ 869178354Ssam rt2560_update_led(sc, 1, 0); 870178354Ssam 871178354Ssam if (ic->ic_opmode != IEEE80211_M_MONITOR) { 872178354Ssam callout_reset(&sc->rssadapt_ch, hz / 10, 873178354Ssam rt2560_update_rssadapt, sc); 874178354Ssam 875173273Ssam rt2560_enable_tsf_sync(sc); 876173273Ssam } 877173273Ssam break; 878173273Ssam } 879173273Ssam 880173273Ssam return (error != 0) ? error : sc->sc_newstate(ic, nstate, arg); 881173273Ssam} 882173273Ssam 883173273Ssam/* 884173273Ssam * Read 16 bits at address 'addr' from the serial EEPROM (either 93C46 or 885173273Ssam * 93C66). 886173273Ssam */ 887173273Ssamstatic uint16_t 888173273Ssamrt2560_eeprom_read(struct rt2560_softc *sc, uint8_t addr) 889173273Ssam{ 890173273Ssam uint32_t tmp; 891173273Ssam uint16_t val; 892173273Ssam int n; 893173273Ssam 894173273Ssam /* clock C once before the first command */ 895173273Ssam RT2560_EEPROM_CTL(sc, 0); 896173273Ssam 897173273Ssam RT2560_EEPROM_CTL(sc, RT2560_S); 898173273Ssam RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_C); 899173273Ssam RT2560_EEPROM_CTL(sc, RT2560_S); 900173273Ssam 901173273Ssam /* write start bit (1) */ 902173273Ssam RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_D); 903173273Ssam RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_D | RT2560_C); 904173273Ssam 905173273Ssam /* write READ opcode (10) */ 906173273Ssam RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_D); 907173273Ssam RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_D | RT2560_C); 908173273Ssam RT2560_EEPROM_CTL(sc, RT2560_S); 909173273Ssam RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_C); 910173273Ssam 911173273Ssam /* write address (A5-A0 or A7-A0) */ 912173273Ssam n = (RAL_READ(sc, RT2560_CSR21) & RT2560_93C46) ? 5 : 7; 913173273Ssam for (; n >= 0; n--) { 914173273Ssam RT2560_EEPROM_CTL(sc, RT2560_S | 915173273Ssam (((addr >> n) & 1) << RT2560_SHIFT_D)); 916173273Ssam RT2560_EEPROM_CTL(sc, RT2560_S | 917173273Ssam (((addr >> n) & 1) << RT2560_SHIFT_D) | RT2560_C); 918173273Ssam } 919173273Ssam 920173273Ssam RT2560_EEPROM_CTL(sc, RT2560_S); 921173273Ssam 922173273Ssam /* read data Q15-Q0 */ 923173273Ssam val = 0; 924173273Ssam for (n = 15; n >= 0; n--) { 925173273Ssam RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_C); 926173273Ssam tmp = RAL_READ(sc, RT2560_CSR21); 927178354Ssam val |= ((tmp & RT2560_Q) >> RT2560_SHIFT_Q) << n; 928173273Ssam RT2560_EEPROM_CTL(sc, RT2560_S); 929173273Ssam } 930173273Ssam 931178354Ssam RT2560_EEPROM_CTL(sc, 0); 932173273Ssam 933173273Ssam /* clear Chip Select and clock C */ 934173273Ssam RT2560_EEPROM_CTL(sc, RT2560_S); 935173273Ssam RT2560_EEPROM_CTL(sc, 0); 936173273Ssam RT2560_EEPROM_CTL(sc, RT2560_C); 937173273Ssam 938173273Ssam return val; 939173273Ssam} 940178354Ssam 941178354Ssam/* 942173273Ssam * Some frames were processed by the hardware cipher engine and are ready for 943173273Ssam * transmission. 944178354Ssam */ 945173273Ssamstatic void 946173273Ssamrt2560_encryption_intr(struct rt2560_softc *sc) 947173273Ssam{ 948173273Ssam struct rt2560_tx_desc *desc; 949173273Ssam int hw; 950173273Ssam 951173273Ssam /* retrieve last descriptor index processed by cipher engine */ 952173273Ssam hw = RAL_READ(sc, RT2560_SECCSR1) - sc->txq.physaddr; 953178354Ssam hw /= RT2560_TX_DESC_SIZE; 954173273Ssam 955173273Ssam bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map, 956173273Ssam BUS_DMASYNC_POSTREAD); 957173273Ssam 958173273Ssam for (; sc->txq.next_encrypt != hw;) { 959173273Ssam desc = &sc->txq.desc[sc->txq.next_encrypt]; 960173273Ssam 961173273Ssam if ((le32toh(desc->flags) & RT2560_TX_BUSY) || 962173273Ssam (le32toh(desc->flags) & RT2560_TX_CIPHER_BUSY)) 963173273Ssam break; 964173273Ssam 965173273Ssam /* for TKIP, swap eiv field to fix a bug in ASIC */ 966173273Ssam if ((le32toh(desc->flags) & RT2560_TX_CIPHER_MASK) == 967173273Ssam RT2560_TX_CIPHER_TKIP) 968173273Ssam desc->eiv = bswap32(desc->eiv); 969173273Ssam 970173273Ssam /* mark the frame ready for transmission */ 971173273Ssam desc->flags |= htole32(RT2560_TX_BUSY | RT2560_TX_VALID); 972173273Ssam 973173273Ssam DPRINTFN(15, ("encryption done idx=%u\n", 974173273Ssam sc->txq.next_encrypt)); 975173273Ssam 976173273Ssam sc->txq.next_encrypt = 977173273Ssam (sc->txq.next_encrypt + 1) % RT2560_TX_RING_COUNT; 978178354Ssam } 979178354Ssam 980178354Ssam bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map, 981178354Ssam BUS_DMASYNC_PREWRITE); 982178354Ssam 983178354Ssam /* kick Tx */ 984178354Ssam RAL_WRITE(sc, RT2560_TXCSR0, RT2560_KICK_TX); 985178354Ssam} 986178354Ssam 987178354Ssamstatic void 988178354Ssamrt2560_tx_intr(struct rt2560_softc *sc) 989178354Ssam{ 990178354Ssam struct ieee80211com *ic = &sc->sc_ic; 991178354Ssam struct ifnet *ifp = ic->ic_ifp; 992178354Ssam struct rt2560_tx_desc *desc; 993178354Ssam struct rt2560_tx_data *data; 994178354Ssam struct rt2560_node *rn; 995178354Ssam 996178354Ssam bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map, 997178354Ssam BUS_DMASYNC_POSTREAD); 998178354Ssam 999178354Ssam for (;;) { 1000178354Ssam desc = &sc->txq.desc[sc->txq.next]; 1001178354Ssam data = &sc->txq.data[sc->txq.next]; 1002173273Ssam 1003173273Ssam if ((le32toh(desc->flags) & RT2560_TX_BUSY) || 1004173273Ssam (le32toh(desc->flags) & RT2560_TX_CIPHER_BUSY) || 1005173273Ssam !(le32toh(desc->flags) & RT2560_TX_VALID)) 1006173273Ssam break; 1007173273Ssam 1008173273Ssam rn = (struct rt2560_node *)data->ni; 1009173273Ssam 1010173273Ssam switch (le32toh(desc->flags) & RT2560_TX_RESULT_MASK) { 1011173273Ssam case RT2560_TX_SUCCESS: 1012173273Ssam DPRINTFN(10, ("data frame sent successfully\n")); 1013178354Ssam if (data->id.id_node != NULL) { 1014178354Ssam ral_rssadapt_raise_rate(ic, &rn->rssadapt, 1015178354Ssam &data->id); 1016178354Ssam } 1017173273Ssam ifp->if_opackets++; 1018178354Ssam break; 1019178354Ssam 1020178354Ssam case RT2560_TX_SUCCESS_RETRY: 1021173273Ssam DPRINTFN(9, ("data frame sent after %u retries\n", 1022173273Ssam (le32toh(desc->flags) >> 5) & 0x7)); 1023173273Ssam ifp->if_opackets++; 1024173273Ssam break; 1025173273Ssam 1026173273Ssam case RT2560_TX_FAIL_RETRY: 1027173273Ssam DPRINTFN(9, ("sending data frame failed (too much " 1028173273Ssam "retries)\n")); 1029173273Ssam if (data->id.id_node != NULL) { 1030173273Ssam ral_rssadapt_lower_rate(ic, data->ni, 1031173273Ssam &rn->rssadapt, &data->id); 1032173273Ssam } 1033173273Ssam ifp->if_oerrors++; 1034173273Ssam break; 1035173273Ssam 1036173273Ssam case RT2560_TX_FAIL_INVALID: 1037173273Ssam case RT2560_TX_FAIL_OTHER: 1038173273Ssam default: 1039173273Ssam device_printf(sc->sc_dev, "sending data frame failed " 1040173273Ssam "0x%08x\n", le32toh(desc->flags)); 1041173273Ssam ifp->if_oerrors++; 1042173273Ssam } 1043173273Ssam 1044173273Ssam bus_dmamap_sync(sc->txq.data_dmat, data->map, 1045173273Ssam BUS_DMASYNC_POSTWRITE); 1046173273Ssam bus_dmamap_unload(sc->txq.data_dmat, data->map); 1047173273Ssam m_freem(data->m); 1048173273Ssam data->m = NULL; 1049173273Ssam ieee80211_free_node(data->ni); 1050173273Ssam data->ni = NULL; 1051173273Ssam 1052173273Ssam /* descriptor is no longer valid */ 1053173273Ssam desc->flags &= ~htole32(RT2560_TX_VALID); 1054173273Ssam 1055173273Ssam DPRINTFN(15, ("tx done idx=%u\n", sc->txq.next)); 1056173273Ssam 1057173273Ssam sc->txq.queued--; 1058173273Ssam sc->txq.next = (sc->txq.next + 1) % RT2560_TX_RING_COUNT; 1059173273Ssam } 1060173273Ssam 1061173273Ssam bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map, 1062173273Ssam BUS_DMASYNC_PREWRITE); 1063173273Ssam 1064173273Ssam sc->sc_tx_timer = 0; 1065173273Ssam ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1066173273Ssam rt2560_start(ifp); 1067173273Ssam} 1068173273Ssam 1069173273Ssamstatic void 1070178354Ssamrt2560_prio_intr(struct rt2560_softc *sc) 1071178354Ssam{ 1072178354Ssam struct ieee80211com *ic = &sc->sc_ic; 1073178354Ssam struct ifnet *ifp = ic->ic_ifp; 1074178354Ssam struct rt2560_tx_desc *desc; 1075178354Ssam struct rt2560_tx_data *data; 1076178354Ssam 1077178354Ssam bus_dmamap_sync(sc->prioq.desc_dmat, sc->prioq.desc_map, 1078178354Ssam BUS_DMASYNC_POSTREAD); 1079173273Ssam 1080173273Ssam for (;;) { 1081178354Ssam desc = &sc->prioq.desc[sc->prioq.next]; 1082173273Ssam data = &sc->prioq.data[sc->prioq.next]; 1083178354Ssam 1084178354Ssam if ((le32toh(desc->flags) & RT2560_TX_BUSY) || 1085178354Ssam !(le32toh(desc->flags) & RT2560_TX_VALID)) 1086178354Ssam break; 1087178354Ssam 1088178354Ssam switch (le32toh(desc->flags) & RT2560_TX_RESULT_MASK) { 1089178354Ssam case RT2560_TX_SUCCESS: 1090181197Ssam DPRINTFN(10, ("mgt frame sent successfully\n")); 1091178354Ssam break; 1092178354Ssam 1093178354Ssam case RT2560_TX_SUCCESS_RETRY: 1094178354Ssam DPRINTFN(9, ("mgt frame sent after %u retries\n", 1095178354Ssam (le32toh(desc->flags) >> 5) & 0x7)); 1096178354Ssam break; 1097178354Ssam 1098178354Ssam case RT2560_TX_FAIL_RETRY: 1099178354Ssam DPRINTFN(9, ("sending mgt frame failed (too much " 1100181197Ssam "retries)\n")); 1101178354Ssam break; 1102173273Ssam 1103173273Ssam case RT2560_TX_FAIL_INVALID: 1104173273Ssam case RT2560_TX_FAIL_OTHER: 1105173273Ssam default: 1106173273Ssam device_printf(sc->sc_dev, "sending mgt frame failed " 1107173273Ssam "0x%08x\n", le32toh(desc->flags)); 1108173273Ssam } 1109173273Ssam 1110173273Ssam bus_dmamap_sync(sc->prioq.data_dmat, data->map, 1111173273Ssam BUS_DMASYNC_POSTWRITE); 1112173273Ssam bus_dmamap_unload(sc->prioq.data_dmat, data->map); 1113173273Ssam m_freem(data->m); 1114173273Ssam data->m = NULL; 1115173273Ssam ieee80211_free_node(data->ni); 1116173273Ssam data->ni = NULL; 1117173273Ssam 1118173273Ssam /* descriptor is no longer valid */ 1119173273Ssam desc->flags &= ~htole32(RT2560_TX_VALID); 1120178354Ssam 1121173273Ssam DPRINTFN(15, ("prio done idx=%u\n", sc->prioq.next)); 1122173273Ssam 1123173273Ssam sc->prioq.queued--; 1124173273Ssam sc->prioq.next = (sc->prioq.next + 1) % RT2560_PRIO_RING_COUNT; 1125173273Ssam } 1126173273Ssam 1127173273Ssam bus_dmamap_sync(sc->prioq.desc_dmat, sc->prioq.desc_map, 1128170530Ssam BUS_DMASYNC_PREWRITE); 1129170530Ssam 1130170530Ssam sc->sc_tx_timer = 0; 1131170530Ssam ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1132170530Ssam rt2560_start(ifp); 1133170530Ssam} 1134170530Ssam 1135170530Ssam/* 1136170530Ssam * Some frames were processed by the hardware cipher engine and are ready for 1137170530Ssam * transmission to the IEEE802.11 layer. 1138170530Ssam */ 1139170530Ssamstatic void 1140178354Ssamrt2560_decryption_intr(struct rt2560_softc *sc) 1141170530Ssam{ 1142170530Ssam struct ieee80211com *ic = &sc->sc_ic; 1143170530Ssam struct ifnet *ifp = ic->ic_ifp; 1144170530Ssam struct rt2560_rx_desc *desc; 1145170530Ssam struct rt2560_rx_data *data; 1146170530Ssam bus_addr_t physaddr; 1147170530Ssam struct ieee80211_frame *wh; 1148170530Ssam struct ieee80211_node *ni; 1149170530Ssam struct rt2560_node *rn; 1150170530Ssam struct mbuf *mnew, *m; 1151170530Ssam int hw, error; 1152170530Ssam 1153170530Ssam /* retrieve last decriptor index processed by cipher engine */ 1154170530Ssam hw = RAL_READ(sc, RT2560_SECCSR0) - sc->rxq.physaddr; 1155170530Ssam hw /= RT2560_RX_DESC_SIZE; 1156173273Ssam 1157173273Ssam bus_dmamap_sync(sc->rxq.desc_dmat, sc->rxq.desc_map, 1158178354Ssam BUS_DMASYNC_POSTREAD); 1159170530Ssam 1160170530Ssam for (; sc->rxq.cur_decrypt != hw;) { 1161170530Ssam desc = &sc->rxq.desc[sc->rxq.cur_decrypt]; 1162173273Ssam data = &sc->rxq.data[sc->rxq.cur_decrypt]; 1163173273Ssam 1164173273Ssam if ((le32toh(desc->flags) & RT2560_RX_BUSY) || 1165173273Ssam (le32toh(desc->flags) & RT2560_RX_CIPHER_BUSY)) 1166173273Ssam break; 1167173273Ssam 1168170530Ssam if (data->drop) { 1169170530Ssam ifp->if_ierrors++; 1170170530Ssam goto skip; 1171170530Ssam } 1172173273Ssam 1173178354Ssam if ((le32toh(desc->flags) & RT2560_RX_CIPHER_MASK) != 0 && 1174170530Ssam (le32toh(desc->flags) & RT2560_RX_ICV_ERROR)) { 1175173273Ssam ifp->if_ierrors++; 1176170530Ssam goto skip; 1177173273Ssam } 1178170530Ssam 1179170530Ssam /* 1180170530Ssam * Try to allocate a new mbuf for this ring element and load it 1181170530Ssam * before processing the current mbuf. If the ring element 1182170530Ssam * cannot be loaded, drop the received packet and reuse the old 1183170530Ssam * mbuf. In the unlikely case that the old mbuf can't be 1184172055Ssam * reloaded either, explicitly panic. 1185170530Ssam */ 1186170530Ssam mnew = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 1187170530Ssam if (mnew == NULL) { 1188173273Ssam ifp->if_ierrors++; 1189173273Ssam goto skip; 1190173273Ssam } 1191173273Ssam 1192173273Ssam bus_dmamap_sync(sc->rxq.data_dmat, data->map, 1193178354Ssam BUS_DMASYNC_POSTREAD); 1194178354Ssam bus_dmamap_unload(sc->rxq.data_dmat, data->map); 1195173273Ssam 1196173273Ssam error = bus_dmamap_load(sc->rxq.data_dmat, data->map, 1197178354Ssam mtod(mnew, void *), MCLBYTES, rt2560_dma_map_addr, 1198173273Ssam &physaddr, 0); 1199173273Ssam if (error != 0) { 1200173273Ssam m_freem(mnew); 1201173273Ssam 1202170530Ssam /* try to reload the old mbuf */ 1203173273Ssam error = bus_dmamap_load(sc->rxq.data_dmat, data->map, 1204173273Ssam mtod(data->m, void *), MCLBYTES, 1205173273Ssam rt2560_dma_map_addr, &physaddr, 0); 1206178354Ssam if (error != 0) { 1207173273Ssam /* very unlikely that it will fail... */ 1208173273Ssam panic("%s: could not load old rx mbuf", 1209173273Ssam device_get_name(sc->sc_dev)); 1210173273Ssam } 1211173273Ssam ifp->if_ierrors++; 1212178354Ssam goto skip; 1213173273Ssam } 1214173273Ssam 1215173273Ssam /* 1216173273Ssam * New mbuf successfully loaded, update Rx ring and continue 1217173273Ssam * processing. 1218173273Ssam */ 1219178354Ssam m = data->m; 1220173273Ssam data->m = mnew; 1221173273Ssam desc->physaddr = htole32(physaddr); 1222173273Ssam 1223173273Ssam /* finalize mbuf */ 1224173273Ssam m->m_pkthdr.rcvif = ifp; 1225173273Ssam m->m_pkthdr.len = m->m_len = 1226173273Ssam (le32toh(desc->flags) >> 16) & 0xfff; 1227173273Ssam 1228173273Ssam if (bpf_peers_present(sc->sc_drvbpf)) { 1229173273Ssam struct rt2560_rx_radiotap_header *tap = &sc->sc_rxtap; 1230170530Ssam uint32_t tsf_lo, tsf_hi; 1231170530Ssam 1232170530Ssam /* get timestamp (low and high 32 bits) */ 1233170530Ssam tsf_hi = RAL_READ(sc, RT2560_CSR17); 1234170530Ssam tsf_lo = RAL_READ(sc, RT2560_CSR16); 1235170530Ssam 1236170530Ssam tap->wr_tsf = 1237170530Ssam htole64(((uint64_t)tsf_hi << 32) | tsf_lo); 1238178354Ssam tap->wr_flags = 0; 1239170530Ssam tap->wr_rate = rt2560_rxrate(desc); 1240170530Ssam tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq); 1241170530Ssam tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags); 1242170530Ssam tap->wr_antenna = sc->rx_ant; 1243170530Ssam tap->wr_antsignal = desc->rssi; 1244170530Ssam 1245170530Ssam bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m); 1246170530Ssam } 1247170530Ssam 1248170530Ssam wh = mtod(m, struct ieee80211_frame *); 1249170530Ssam ni = ieee80211_find_rxnode(ic, 1250170530Ssam (struct ieee80211_frame_min *)wh); 1251170530Ssam 1252170530Ssam /* send the frame to the 802.11 layer */ 1253178354Ssam ieee80211_input(ic, m, ni, desc->rssi, 0); 1254170530Ssam 1255170530Ssam /* give rssi to the rate adatation algorithm */ 1256170530Ssam rn = (struct rt2560_node *)ni; 1257178354Ssam ral_rssadapt_input(ic, ni, &rn->rssadapt, desc->rssi); 1258170530Ssam 1259170530Ssam /* node is no longer needed */ 1260170530Ssam ieee80211_free_node(ni); 1261170530Ssam 1262170530Ssamskip: desc->flags = htole32(RT2560_RX_BUSY); 1263170530Ssam 1264170530Ssam DPRINTFN(15, ("decryption done idx=%u\n", sc->rxq.cur_decrypt)); 1265170530Ssam 1266170530Ssam sc->rxq.cur_decrypt = 1267170530Ssam (sc->rxq.cur_decrypt + 1) % RT2560_RX_RING_COUNT; 1268170530Ssam } 1269170530Ssam 1270170530Ssam bus_dmamap_sync(sc->rxq.desc_dmat, sc->rxq.desc_map, 1271170530Ssam BUS_DMASYNC_PREWRITE); 1272170530Ssam} 1273170530Ssam 1274170530Ssam/* 1275170530Ssam * Some frames were received. Pass them to the hardware cipher engine before 1276170530Ssam * sending them to the 802.11 layer. 1277170530Ssam */ 1278170530Ssamstatic void 1279170530Ssamrt2560_rx_intr(struct rt2560_softc *sc) 1280170530Ssam{ 1281170530Ssam struct rt2560_rx_desc *desc; 1282178354Ssam struct rt2560_rx_data *data; 1283170530Ssam 1284170530Ssam bus_dmamap_sync(sc->rxq.desc_dmat, sc->rxq.desc_map, 1285170530Ssam BUS_DMASYNC_POSTREAD); 1286170530Ssam 1287170530Ssam for (;;) { 1288170530Ssam desc = &sc->rxq.desc[sc->rxq.cur]; 1289170530Ssam data = &sc->rxq.data[sc->rxq.cur]; 1290170530Ssam 1291170530Ssam if ((le32toh(desc->flags) & RT2560_RX_BUSY) || 1292170530Ssam (le32toh(desc->flags) & RT2560_RX_CIPHER_BUSY)) 1293170530Ssam break; 1294170530Ssam 1295170530Ssam data->drop = 0; 1296170530Ssam 1297170530Ssam if ((le32toh(desc->flags) & RT2560_RX_PHY_ERROR) || 1298170530Ssam (le32toh(desc->flags) & RT2560_RX_CRC_ERROR)) { 1299170530Ssam /* 1300170530Ssam * This should not happen since we did not request 1301170530Ssam * to receive those frames when we filled RXCSR0. 1302170530Ssam */ 1303170530Ssam DPRINTFN(5, ("PHY or CRC error flags 0x%08x\n", 1304170530Ssam le32toh(desc->flags))); 1305170530Ssam data->drop = 1; 1306170530Ssam } 1307170530Ssam 1308170530Ssam if (((le32toh(desc->flags) >> 16) & 0xfff) > MCLBYTES) { 1309170530Ssam DPRINTFN(5, ("bad length\n")); 1310178354Ssam data->drop = 1; 1311170530Ssam } 1312170530Ssam 1313178354Ssam /* mark the frame for decryption */ 1314170530Ssam desc->flags |= htole32(RT2560_RX_CIPHER_BUSY); 1315170530Ssam 1316170530Ssam DPRINTFN(15, ("rx done idx=%u\n", sc->rxq.cur)); 1317170530Ssam 1318170530Ssam sc->rxq.cur = (sc->rxq.cur + 1) % RT2560_RX_RING_COUNT; 1319170530Ssam } 1320170530Ssam 1321170530Ssam bus_dmamap_sync(sc->rxq.desc_dmat, sc->rxq.desc_map, 1322170530Ssam BUS_DMASYNC_PREWRITE); 1323170530Ssam 1324170530Ssam /* kick decrypt */ 1325170530Ssam RAL_WRITE(sc, RT2560_SECCSR0, RT2560_KICK_DECRYPT); 1326170530Ssam} 1327170530Ssam 1328170530Ssam/* 1329170530Ssam * This function is called periodically in IBSS mode when a new beacon must be 1330170530Ssam * sent out. 1331170530Ssam */ 1332170530Ssamstatic void 1333170530Ssamrt2560_beacon_expire(struct rt2560_softc *sc) 1334170530Ssam{ 1335170530Ssam struct ieee80211com *ic = &sc->sc_ic; 1336170530Ssam struct rt2560_tx_data *data; 1337170530Ssam 1338170530Ssam if (ic->ic_opmode != IEEE80211_M_IBSS && 1339170530Ssam ic->ic_opmode != IEEE80211_M_HOSTAP) 1340170530Ssam return; 1341170530Ssam 1342170530Ssam data = &sc->bcnq.data[sc->bcnq.next]; 1343170530Ssam 1344170530Ssam bus_dmamap_sync(sc->bcnq.data_dmat, data->map, BUS_DMASYNC_POSTWRITE); 1345170530Ssam bus_dmamap_unload(sc->bcnq.data_dmat, data->map); 1346170530Ssam 1347170530Ssam ieee80211_beacon_update(ic, data->ni, &sc->sc_bo, data->m, 1); 1348170530Ssam 1349170530Ssam if (bpf_peers_present(ic->ic_rawbpf)) 1350170530Ssam bpf_mtap(ic->ic_rawbpf, data->m); 1351170530Ssam 1352170530Ssam rt2560_tx_bcn(sc, data->m, data->ni); 1353170530Ssam 1354170530Ssam DPRINTFN(15, ("beacon expired\n")); 1355170530Ssam 1356170530Ssam sc->bcnq.next = (sc->bcnq.next + 1) % RT2560_BEACON_RING_COUNT; 1357170530Ssam} 1358170530Ssam 1359170530Ssam/* ARGSUSED */ 1360170530Ssamstatic void 1361170530Ssamrt2560_wakeup_expire(struct rt2560_softc *sc) 1362170530Ssam{ 1363170530Ssam DPRINTFN(2, ("wakeup expired\n")); 1364170530Ssam} 1365170530Ssam 1366170530Ssamvoid 1367170530Ssamrt2560_intr(void *arg) 1368170530Ssam{ 1369173273Ssam struct rt2560_softc *sc = arg; 1370173273Ssam struct ifnet *ifp = sc->sc_ifp; 1371173273Ssam uint32_t r; 1372170530Ssam 1373170530Ssam RAL_LOCK(sc); 1374170530Ssam 1375170530Ssam /* disable interrupts */ 1376170530Ssam RAL_WRITE(sc, RT2560_CSR8, 0xffffffff); 1377170530Ssam 1378170530Ssam /* don't re-enable interrupts if we're shutting down */ 1379170530Ssam if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { 1380170530Ssam RAL_UNLOCK(sc); 1381170530Ssam return; 1382170530Ssam } 1383170530Ssam 1384170530Ssam r = RAL_READ(sc, RT2560_CSR7); 1385170530Ssam RAL_WRITE(sc, RT2560_CSR7, r); 1386170530Ssam 1387170530Ssam if (r & RT2560_BEACON_EXPIRE) 1388170530Ssam rt2560_beacon_expire(sc); 1389170530Ssam 1390170530Ssam if (r & RT2560_WAKEUP_EXPIRE) 1391170530Ssam rt2560_wakeup_expire(sc); 1392170530Ssam 1393170530Ssam if (r & RT2560_ENCRYPTION_DONE) 1394170530Ssam rt2560_encryption_intr(sc); 1395170530Ssam 1396170530Ssam if (r & RT2560_TX_DONE) 1397170530Ssam rt2560_tx_intr(sc); 1398170530Ssam 1399170530Ssam if (r & RT2560_PRIO_DONE) 1400170530Ssam rt2560_prio_intr(sc); 1401170530Ssam 1402178354Ssam if (r & RT2560_DECRYPTION_DONE) 1403170530Ssam rt2560_decryption_intr(sc); 1404170530Ssam 1405170530Ssam if (r & RT2560_RX_DONE) 1406170530Ssam rt2560_rx_intr(sc); 1407170530Ssam 1408170530Ssam /* re-enable interrupts */ 1409170530Ssam RAL_WRITE(sc, RT2560_CSR8, RT2560_INTR_MASK); 1410170530Ssam 1411170530Ssam RAL_UNLOCK(sc); 1412170530Ssam} 1413170530Ssam 1414170530Ssam/* quickly determine if a given rate is CCK or OFDM */ 1415170530Ssam#define RAL_RATE_IS_OFDM(rate) ((rate) >= 12 && (rate) != 22) 1416170530Ssam 1417170530Ssam#define RAL_ACK_SIZE 14 /* 10 + 4(FCS) */ 1418170530Ssam#define RAL_CTS_SIZE 14 /* 10 + 4(FCS) */ 1419170530Ssam 1420170530Ssam#define RAL_SIFS 10 /* us */ 1421170530Ssam 1422170530Ssam#define RT2560_TXRX_TURNAROUND 10 /* us */ 1423170530Ssam 1424178354Ssam/* 1425170530Ssam * This function is only used by the Rx radiotap code. 1426170530Ssam */ 1427170530Ssamstatic uint8_t 1428173273Ssamrt2560_rxrate(struct rt2560_rx_desc *desc) 1429173273Ssam{ 1430173273Ssam if (le32toh(desc->flags) & RT2560_RX_OFDM) { 1431173273Ssam /* reverse function of rt2560_plcp_signal */ 1432170530Ssam switch (desc->rate) { 1433170530Ssam case 0xb: return 12; 1434170530Ssam case 0xf: return 18; 1435170530Ssam case 0xa: return 24; 1436170530Ssam case 0xe: return 36; 1437173273Ssam case 0x9: return 48; 1438173273Ssam case 0xd: return 72; 1439173273Ssam case 0x8: return 96; 1440173273Ssam case 0xc: return 108; 1441173273Ssam } 1442173273Ssam } else { 1443178354Ssam if (desc->rate == 10) 1444170530Ssam return 2; 1445170530Ssam if (desc->rate == 20) 1446170530Ssam return 4; 1447170530Ssam if (desc->rate == 55) 1448173273Ssam return 11; 1449178354Ssam if (desc->rate == 110) 1450173273Ssam return 22; 1451173273Ssam } 1452173273Ssam return 2; /* should not get there */ 1453173273Ssam} 1454173273Ssam 1455178354Ssam/* 1456170530Ssam * Return the expected ack rate for a frame transmitted at rate `rate'. 1457173273Ssam * XXX: this should depend on the destination node basic rate set. 1458170530Ssam */ 1459170530Ssamstatic int 1460170530Ssamrt2560_ack_rate(struct ieee80211com *ic, int rate) 1461170530Ssam{ 1462170530Ssam switch (rate) { 1463170530Ssam /* CCK rates */ 1464170530Ssam case 2: 1465170530Ssam return 2; 1466170530Ssam case 4: 1467170530Ssam case 11: 1468170530Ssam case 22: 1469170530Ssam return (ic->ic_curmode == IEEE80211_MODE_11B) ? 4 : rate; 1470170530Ssam 1471170530Ssam /* OFDM rates */ 1472170530Ssam case 12: 1473170530Ssam case 18: 1474170530Ssam return 12; 1475170530Ssam case 24: 1476173273Ssam case 36: 1477173273Ssam return 24; 1478175877Ssam case 48: 1479178354Ssam case 72: 1480173273Ssam case 96: 1481173273Ssam case 108: 1482173273Ssam return 48; 1483173273Ssam } 1484178354Ssam 1485173273Ssam /* default to 1Mbps */ 1486173273Ssam return 2; 1487173273Ssam} 1488178354Ssam 1489173273Ssam/* 1490173273Ssam * Compute the duration (in us) needed to transmit `len' bytes at rate `rate'. 1491173273Ssam * The function automatically determines the operating mode depending on the 1492173273Ssam * given rate. `flags' indicates whether short preamble is in use or not. 1493173273Ssam */ 1494178354Ssamstatic uint16_t 1495173273Ssamrt2560_txtime(int len, int rate, uint32_t flags) 1496173273Ssam{ 1497173273Ssam uint16_t txtime; 1498178354Ssam 1499170530Ssam if (RAL_RATE_IS_OFDM(rate)) { 1500170530Ssam /* IEEE Std 802.11a-1999, pp. 37 */ 1501170530Ssam txtime = (8 + 4 * len + 3 + rate - 1) / rate; 1502170530Ssam txtime = 16 + 4 + 4 * txtime + 6; 1503170530Ssam } else { 1504170530Ssam /* IEEE Std 802.11b-1999, pp. 28 */ 1505170530Ssam txtime = (16 * len + rate - 1) / rate; 1506170530Ssam if (rate != 2 && (flags & IEEE80211_F_SHPREAMBLE)) 1507170530Ssam txtime += 72 + 24; 1508170530Ssam else 1509170530Ssam txtime += 144 + 48; 1510170530Ssam } 1511170530Ssam 1512170530Ssam return txtime; 1513170530Ssam} 1514178354Ssam 1515170530Ssamstatic uint8_t 1516170530Ssamrt2560_plcp_signal(int rate) 1517170530Ssam{ 1518170530Ssam switch (rate) { 1519170530Ssam /* CCK rates (returned values are device-dependent) */ 1520170530Ssam case 2: return 0x0; 1521170530Ssam case 4: return 0x1; 1522170530Ssam case 11: return 0x2; 1523170530Ssam case 22: return 0x3; 1524170530Ssam 1525170530Ssam /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */ 1526170530Ssam case 12: return 0xb; 1527170530Ssam case 18: return 0xf; 1528170530Ssam case 24: return 0xa; 1529170530Ssam case 36: return 0xe; 1530170530Ssam case 48: return 0x9; 1531170530Ssam case 72: return 0xd; 1532173273Ssam case 96: return 0x8; 1533170530Ssam case 108: return 0xc; 1534170530Ssam 1535170530Ssam /* unsupported rates (should not get there) */ 1536170530Ssam default: return 0xff; 1537170530Ssam } 1538170530Ssam} 1539170530Ssam 1540170530Ssamstatic void 1541170530Ssamrt2560_setup_tx_desc(struct rt2560_softc *sc, struct rt2560_tx_desc *desc, 1542170530Ssam uint32_t flags, int len, int rate, int encrypt, bus_addr_t physaddr) 1543170530Ssam{ 1544170530Ssam struct ieee80211com *ic = &sc->sc_ic; 1545178354Ssam uint16_t plcp_length; 1546170530Ssam int remainder; 1547170530Ssam 1548170530Ssam desc->flags = htole32(flags); 1549170530Ssam desc->flags |= htole32(len << 16); 1550170530Ssam desc->flags |= encrypt ? htole32(RT2560_TX_CIPHER_BUSY) : 1551170530Ssam htole32(RT2560_TX_BUSY | RT2560_TX_VALID); 1552178354Ssam 1553170530Ssam desc->physaddr = htole32(physaddr); 1554170530Ssam desc->wme = htole16( 1555170530Ssam RT2560_AIFSN(2) | 1556178354Ssam RT2560_LOGCWMIN(3) | 1557170530Ssam RT2560_LOGCWMAX(8)); 1558170530Ssam 1559170530Ssam /* setup PLCP fields */ 1560170530Ssam desc->plcp_signal = rt2560_plcp_signal(rate); 1561170530Ssam desc->plcp_service = 4; 1562170530Ssam 1563170530Ssam len += IEEE80211_CRC_LEN; 1564170530Ssam if (RAL_RATE_IS_OFDM(rate)) { 1565170530Ssam desc->flags |= htole32(RT2560_TX_OFDM); 1566178354Ssam 1567170530Ssam plcp_length = len & 0xfff; 1568173273Ssam desc->plcp_length_hi = plcp_length >> 6; 1569170530Ssam desc->plcp_length_lo = plcp_length & 0x3f; 1570170530Ssam } else { 1571170530Ssam plcp_length = (16 * len + rate - 1) / rate; 1572170530Ssam if (rate == 22) { 1573173273Ssam remainder = (16 * len) % 22; 1574178354Ssam if (remainder != 0 && remainder < 7) 1575173273Ssam desc->plcp_service |= RT2560_PLCP_LENGEXT; 1576173273Ssam } 1577173273Ssam desc->plcp_length_hi = plcp_length >> 8; 1578170530Ssam desc->plcp_length_lo = plcp_length & 0xff; 1579178354Ssam 1580170530Ssam if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) 1581170530Ssam desc->plcp_signal |= 0x08; 1582170530Ssam } 1583178354Ssam} 1584170530Ssam 1585170530Ssamstatic int 1586170530Ssamrt2560_tx_bcn(struct rt2560_softc *sc, struct mbuf *m0, 1587170530Ssam struct ieee80211_node *ni) 1588178354Ssam{ 1589170530Ssam struct ieee80211com *ic = &sc->sc_ic; 1590170530Ssam struct rt2560_tx_desc *desc; 1591170530Ssam struct rt2560_tx_data *data; 1592178354Ssam bus_dma_segment_t segs[RT2560_MAX_SCATTER]; 1593170530Ssam int nsegs, rate, error; 1594170530Ssam 1595170530Ssam desc = &sc->bcnq.desc[sc->bcnq.cur]; 1596170530Ssam data = &sc->bcnq.data[sc->bcnq.cur]; 1597170530Ssam 1598170530Ssam rate = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ? 12 : 2; 1599170530Ssam 1600170530Ssam error = bus_dmamap_load_mbuf_sg(sc->bcnq.data_dmat, data->map, m0, 1601170530Ssam segs, &nsegs, BUS_DMA_NOWAIT); 1602178354Ssam if (error != 0) { 1603178354Ssam device_printf(sc->sc_dev, "could not map mbuf (error %d)\n", 1604178354Ssam error); 1605178354Ssam m_freem(m0); 1606178354Ssam return error; 1607178354Ssam } 1608178354Ssam 1609178354Ssam if (bpf_peers_present(sc->sc_drvbpf)) { 1610178354Ssam struct rt2560_tx_radiotap_header *tap = &sc->sc_txtap; 1611178354Ssam 1612178354Ssam tap->wt_flags = 0; 1613178354Ssam tap->wt_rate = rate; 1614178354Ssam tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); 1615178354Ssam tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); 1616178354Ssam tap->wt_antenna = sc->tx_ant; 1617178354Ssam 1618178354Ssam bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m0); 1619178354Ssam } 1620178354Ssam 1621178354Ssam data->m = m0; 1622178354Ssam data->ni = ni; 1623178354Ssam 1624178354Ssam rt2560_setup_tx_desc(sc, desc, RT2560_TX_IFS_NEWBACKOFF | 1625178354Ssam RT2560_TX_TIMESTAMP, m0->m_pkthdr.len, rate, 0, segs->ds_addr); 1626178354Ssam 1627178354Ssam DPRINTFN(10, ("sending beacon frame len=%u idx=%u rate=%u\n", 1628178354Ssam m0->m_pkthdr.len, sc->bcnq.cur, rate)); 1629178354Ssam 1630178354Ssam bus_dmamap_sync(sc->bcnq.data_dmat, data->map, BUS_DMASYNC_PREWRITE); 1631178354Ssam bus_dmamap_sync(sc->bcnq.desc_dmat, sc->bcnq.desc_map, 1632178354Ssam BUS_DMASYNC_PREWRITE); 1633178354Ssam 1634178354Ssam sc->bcnq.cur = (sc->bcnq.cur + 1) % RT2560_BEACON_RING_COUNT; 1635170530Ssam 1636170530Ssam return 0; 1637170530Ssam} 1638170530Ssam 1639170530Ssamstatic int 1640170530Ssamrt2560_tx_mgt(struct rt2560_softc *sc, struct mbuf *m0, 1641170530Ssam struct ieee80211_node *ni) 1642170530Ssam{ 1643170530Ssam struct ieee80211com *ic = &sc->sc_ic; 1644170530Ssam struct rt2560_tx_desc *desc; 1645170530Ssam struct rt2560_tx_data *data; 1646170530Ssam struct ieee80211_frame *wh; 1647170530Ssam bus_dma_segment_t segs[RT2560_MAX_SCATTER]; 1648170530Ssam uint16_t dur; 1649170530Ssam uint32_t flags = 0; 1650170530Ssam int nsegs, rate, error; 1651170530Ssam 1652170530Ssam desc = &sc->prioq.desc[sc->prioq.cur]; 1653170530Ssam data = &sc->prioq.data[sc->prioq.cur]; 1654173273Ssam 1655173273Ssam rate = IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ? 12 : 2; 1656173273Ssam 1657170530Ssam error = bus_dmamap_load_mbuf_sg(sc->prioq.data_dmat, data->map, m0, 1658170530Ssam segs, &nsegs, 0); 1659170530Ssam if (error != 0) { 1660170530Ssam device_printf(sc->sc_dev, "could not map mbuf (error %d)\n", 1661170530Ssam error); 1662170530Ssam m_freem(m0); 1663170530Ssam return error; 1664170530Ssam } 1665170530Ssam 1666170530Ssam if (bpf_peers_present(sc->sc_drvbpf)) { 1667170530Ssam struct rt2560_tx_radiotap_header *tap = &sc->sc_txtap; 1668170530Ssam 1669178354Ssam tap->wt_flags = 0; 1670173273Ssam tap->wt_rate = rate; 1671173273Ssam tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); 1672173273Ssam tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); 1673178354Ssam tap->wt_antenna = sc->tx_ant; 1674178354Ssam 1675178354Ssam bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m0); 1676178354Ssam } 1677170530Ssam 1678170530Ssam data->m = m0; 1679170530Ssam data->ni = ni; 1680178953Ssam 1681178953Ssam wh = mtod(m0, struct ieee80211_frame *); 1682178953Ssam 1683178953Ssam if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { 1684170530Ssam flags |= RT2560_TX_ACK; 1685170530Ssam 1686170530Ssam dur = rt2560_txtime(RAL_ACK_SIZE, rate, ic->ic_flags) + 1687170530Ssam RAL_SIFS; 1688170530Ssam *(uint16_t *)wh->i_dur = htole16(dur); 1689173273Ssam 1690173273Ssam /* tell hardware to add timestamp for probe responses */ 1691173273Ssam if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == 1692173273Ssam IEEE80211_FC0_TYPE_MGT && 1693173273Ssam (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == 1694173273Ssam IEEE80211_FC0_SUBTYPE_PROBE_RESP) 1695173273Ssam flags |= RT2560_TX_TIMESTAMP; 1696178354Ssam } 1697173273Ssam 1698173273Ssam rt2560_setup_tx_desc(sc, desc, flags, m0->m_pkthdr.len, rate, 0, 1699173273Ssam segs->ds_addr); 1700173273Ssam 1701178354Ssam bus_dmamap_sync(sc->prioq.data_dmat, data->map, BUS_DMASYNC_PREWRITE); 1702173273Ssam bus_dmamap_sync(sc->prioq.desc_dmat, sc->prioq.desc_map, 1703178354Ssam BUS_DMASYNC_PREWRITE); 1704173273Ssam 1705173273Ssam DPRINTFN(10, ("sending mgt frame len=%u idx=%u rate=%u\n", 1706173273Ssam m0->m_pkthdr.len, sc->prioq.cur, rate)); 1707173273Ssam 1708173273Ssam /* kick prio */ 1709173273Ssam sc->prioq.queued++; 1710173273Ssam sc->prioq.cur = (sc->prioq.cur + 1) % RT2560_PRIO_RING_COUNT; 1711173273Ssam RAL_WRITE(sc, RT2560_TXCSR0, RT2560_KICK_PRIO); 1712178354Ssam 1713173273Ssam return 0; 1714173273Ssam} 1715178354Ssam 1716173273Ssam/* 1717173273Ssam * Build a RTS control frame. 1718173273Ssam */ 1719173273Ssamstatic struct mbuf * 1720170530Ssamrt2560_get_rts(struct rt2560_softc *sc, struct ieee80211_frame *wh, 1721170530Ssam uint16_t dur) 1722170530Ssam{ 1723170530Ssam struct ieee80211_frame_rts *rts; 1724170530Ssam struct mbuf *m; 1725170530Ssam 1726170530Ssam MGETHDR(m, M_DONTWAIT, MT_DATA); 1727170530Ssam if (m == NULL) { 1728178354Ssam sc->sc_ic.ic_stats.is_tx_nobuf++; 1729170530Ssam device_printf(sc->sc_dev, "could not allocate RTS frame\n"); 1730170530Ssam return NULL; 1731170530Ssam } 1732170530Ssam 1733170530Ssam rts = mtod(m, struct ieee80211_frame_rts *); 1734178354Ssam 1735170530Ssam rts->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_CTL | 1736170530Ssam IEEE80211_FC0_SUBTYPE_RTS; 1737170530Ssam rts->i_fc[1] = IEEE80211_FC1_DIR_NODS; 1738170530Ssam *(uint16_t *)rts->i_dur = htole16(dur); 1739170530Ssam IEEE80211_ADDR_COPY(rts->i_ra, wh->i_addr1); 1740170530Ssam IEEE80211_ADDR_COPY(rts->i_ta, wh->i_addr2); 1741170530Ssam 1742170530Ssam m->m_pkthdr.len = m->m_len = sizeof (struct ieee80211_frame_rts); 1743170530Ssam 1744170530Ssam return m; 1745170530Ssam} 1746170530Ssam 1747170530Ssamstatic int 1748170530Ssamrt2560_tx_data(struct rt2560_softc *sc, struct mbuf *m0, 1749170530Ssam struct ieee80211_node *ni) 1750170530Ssam{ 1751170530Ssam struct ieee80211com *ic = &sc->sc_ic; 1752170530Ssam struct rt2560_tx_desc *desc; 1753170530Ssam struct rt2560_tx_data *data; 1754170530Ssam struct rt2560_node *rn; 1755170530Ssam struct ieee80211_rateset *rs; 1756178354Ssam struct ieee80211_frame *wh; 1757170530Ssam struct ieee80211_key *k; 1758170530Ssam struct mbuf *mnew; 1759170530Ssam bus_dma_segment_t segs[RT2560_MAX_SCATTER]; 1760170530Ssam uint16_t dur; 1761170530Ssam uint32_t flags = 0; 1762170530Ssam int nsegs, rate, error; 1763170530Ssam 1764170530Ssam wh = mtod(m0, struct ieee80211_frame *); 1765170530Ssam 1766170530Ssam if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) { 1767170530Ssam rs = &ic->ic_sup_rates[ic->ic_curmode]; 1768170530Ssam rate = rs->rs_rates[ic->ic_fixed_rate]; 1769170530Ssam } else { 1770170530Ssam rs = &ni->ni_rates; 1771170530Ssam rn = (struct rt2560_node *)ni; 1772178354Ssam ni->ni_txrate = ral_rssadapt_choose(&rn->rssadapt, rs, wh, 1773178354Ssam m0->m_pkthdr.len, NULL, 0); 1774170530Ssam rate = rs->rs_rates[ni->ni_txrate]; 1775170530Ssam } 1776178354Ssam rate &= IEEE80211_RATE_VAL; 1777173273Ssam 1778173273Ssam if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 1779170530Ssam k = ieee80211_crypto_encap(ic, ni, m0); 1780178354Ssam if (k == NULL) { 1781170530Ssam m_freem(m0); 1782170530Ssam return ENOBUFS; 1783170530Ssam } 1784170530Ssam 1785170530Ssam /* packet header may have moved, reset our local pointer */ 1786170530Ssam wh = mtod(m0, struct ieee80211_frame *); 1787170530Ssam } 1788170530Ssam 1789170530Ssam /* 1790170530Ssam * IEEE Std 802.11-1999, pp 82: "A STA shall use an RTS/CTS exchange 1791170530Ssam * for directed frames only when the length of the MPDU is greater 1792170530Ssam * than the length threshold indicated by [...]" ic_rtsthreshold. 1793170530Ssam */ 1794170530Ssam if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && 1795170530Ssam m0->m_pkthdr.len > ic->ic_rtsthreshold) { 1796170530Ssam struct mbuf *m; 1797178354Ssam uint16_t dur; 1798170530Ssam int rtsrate, ackrate; 1799170530Ssam 1800170530Ssam rtsrate = IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan) ? 12 : 2; 1801170530Ssam ackrate = rt2560_ack_rate(ic, rate); 1802170530Ssam 1803178354Ssam dur = rt2560_txtime(m0->m_pkthdr.len + 4, rate, ic->ic_flags) + 1804170530Ssam rt2560_txtime(RAL_CTS_SIZE, rtsrate, ic->ic_flags) + 1805170530Ssam rt2560_txtime(RAL_ACK_SIZE, ackrate, ic->ic_flags) + 1806170530Ssam 3 * RAL_SIFS; 1807170530Ssam 1808170530Ssam m = rt2560_get_rts(sc, wh, dur); 1809170530Ssam 1810170530Ssam desc = &sc->txq.desc[sc->txq.cur_encrypt]; 1811170530Ssam data = &sc->txq.data[sc->txq.cur_encrypt]; 1812170530Ssam 1813170530Ssam error = bus_dmamap_load_mbuf_sg(sc->txq.data_dmat, data->map, 1814170530Ssam m, segs, &nsegs, 0); 1815170530Ssam if (error != 0) { 1816170530Ssam device_printf(sc->sc_dev, 1817178354Ssam "could not map mbuf (error %d)\n", error); 1818170530Ssam m_freem(m); 1819170530Ssam m_freem(m0); 1820170530Ssam return error; 1821170530Ssam } 1822170530Ssam 1823170530Ssam /* avoid multiple free() of the same node for each fragment */ 1824170530Ssam ieee80211_ref_node(ni); 1825170530Ssam 1826170530Ssam data->m = m; 1827170530Ssam data->ni = ni; 1828170530Ssam 1829170530Ssam /* RTS frames are not taken into account for rssadapt */ 1830170530Ssam data->id.id_node = NULL; 1831170530Ssam 1832170530Ssam rt2560_setup_tx_desc(sc, desc, RT2560_TX_ACK | 1833170530Ssam RT2560_TX_MORE_FRAG, m->m_pkthdr.len, rtsrate, 1, 1834170530Ssam segs->ds_addr); 1835170530Ssam 1836170530Ssam bus_dmamap_sync(sc->txq.data_dmat, data->map, 1837170530Ssam BUS_DMASYNC_PREWRITE); 1838170530Ssam 1839178354Ssam sc->txq.queued++; 1840170530Ssam sc->txq.cur_encrypt = 1841173273Ssam (sc->txq.cur_encrypt + 1) % RT2560_TX_RING_COUNT; 1842173273Ssam 1843173273Ssam /* 1844173273Ssam * IEEE Std 802.11-1999: when an RTS/CTS exchange is used, the 1845170530Ssam * asynchronous data frame shall be transmitted after the CTS 1846170530Ssam * frame and a SIFS period. 1847170530Ssam */ 1848170530Ssam flags |= RT2560_TX_LONG_RETRY | RT2560_TX_IFS_SIFS; 1849170530Ssam } 1850170530Ssam 1851170530Ssam data = &sc->txq.data[sc->txq.cur_encrypt]; 1852178354Ssam desc = &sc->txq.desc[sc->txq.cur_encrypt]; 1853170530Ssam 1854170530Ssam error = bus_dmamap_load_mbuf_sg(sc->txq.data_dmat, data->map, m0, 1855170530Ssam segs, &nsegs, 0); 1856170530Ssam if (error != 0 && error != EFBIG) { 1857170530Ssam device_printf(sc->sc_dev, "could not map mbuf (error %d)\n", 1858170530Ssam error); 1859170530Ssam m_freem(m0); 1860170530Ssam return error; 1861170530Ssam } 1862170530Ssam if (error != 0) { 1863170530Ssam mnew = m_defrag(m0, M_DONTWAIT); 1864170530Ssam if (mnew == NULL) { 1865170530Ssam device_printf(sc->sc_dev, 1866170530Ssam "could not defragment mbuf\n"); 1867180309Ssam m_freem(m0); 1868170530Ssam return ENOBUFS; 1869170530Ssam } 1870170530Ssam m0 = mnew; 1871170530Ssam 1872178354Ssam error = bus_dmamap_load_mbuf_sg(sc->txq.data_dmat, data->map, 1873170530Ssam m0, segs, &nsegs, 0); 1874170530Ssam if (error != 0) { 1875170530Ssam device_printf(sc->sc_dev, 1876170530Ssam "could not map mbuf (error %d)\n", error); 1877170530Ssam m_freem(m0); 1878170530Ssam return error; 1879170530Ssam } 1880170530Ssam 1881170530Ssam /* packet header may have moved, reset our local pointer */ 1882170530Ssam wh = mtod(m0, struct ieee80211_frame *); 1883170530Ssam } 1884178354Ssam 1885170530Ssam if (bpf_peers_present(sc->sc_drvbpf)) { 1886170530Ssam struct rt2560_tx_radiotap_header *tap = &sc->sc_txtap; 1887178354Ssam 1888170530Ssam tap->wt_flags = 0; 1889178354Ssam tap->wt_rate = rate; 1890170530Ssam tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); 1891170530Ssam tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); 1892170530Ssam tap->wt_antenna = sc->tx_ant; 1893170530Ssam 1894170530Ssam bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m0); 1895170530Ssam } 1896170530Ssam 1897170530Ssam data->m = m0; 1898170530Ssam data->ni = ni; 1899178354Ssam 1900170530Ssam /* remember link conditions for rate adaptation algorithm */ 1901170530Ssam if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) { 1902170530Ssam data->id.id_len = m0->m_pkthdr.len; 1903170530Ssam data->id.id_rateidx = ni->ni_txrate; 1904170530Ssam data->id.id_node = ni; 1905170530Ssam data->id.id_rssi = ni->ni_rssi; 1906170530Ssam } else 1907170530Ssam data->id.id_node = NULL; 1908178354Ssam 1909170530Ssam if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) { 1910170530Ssam flags |= RT2560_TX_ACK; 1911178354Ssam 1912178354Ssam dur = rt2560_txtime(RAL_ACK_SIZE, rt2560_ack_rate(ic, rate), 1913170530Ssam ic->ic_flags) + RAL_SIFS; 1914170530Ssam *(uint16_t *)wh->i_dur = htole16(dur); 1915170530Ssam } 1916170530Ssam 1917170530Ssam rt2560_setup_tx_desc(sc, desc, flags, m0->m_pkthdr.len, rate, 1, 1918170530Ssam segs->ds_addr); 1919170530Ssam 1920170530Ssam bus_dmamap_sync(sc->txq.data_dmat, data->map, BUS_DMASYNC_PREWRITE); 1921170530Ssam bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map, 1922170530Ssam BUS_DMASYNC_PREWRITE); 1923170530Ssam 1924170530Ssam DPRINTFN(10, ("sending data frame len=%u idx=%u rate=%u\n", 1925170530Ssam m0->m_pkthdr.len, sc->txq.cur_encrypt, rate)); 1926170530Ssam 1927170530Ssam /* kick encrypt */ 1928170530Ssam sc->txq.queued++; 1929170530Ssam sc->txq.cur_encrypt = (sc->txq.cur_encrypt + 1) % RT2560_TX_RING_COUNT; 1930170530Ssam RAL_WRITE(sc, RT2560_SECCSR1, RT2560_KICK_ENCRYPT); 1931170530Ssam 1932170530Ssam return 0; 1933170530Ssam} 1934170530Ssam 1935170530Ssamstatic void 1936170530Ssamrt2560_start(struct ifnet *ifp) 1937170530Ssam{ 1938170530Ssam struct rt2560_softc *sc = ifp->if_softc; 1939170530Ssam struct ieee80211com *ic = &sc->sc_ic; 1940170530Ssam struct mbuf *m0; 1941170530Ssam struct ether_header *eh; 1942170530Ssam struct ieee80211_node *ni; 1943170530Ssam 1944170530Ssam RAL_LOCK(sc); 1945170530Ssam 1946170530Ssam /* prevent management frames from being sent if we're not ready */ 1947178354Ssam if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { 1948170530Ssam RAL_UNLOCK(sc); 1949173865Ssam return; 1950170530Ssam } 1951170530Ssam 1952178354Ssam for (;;) { 1953173273Ssam IF_POLL(&ic->ic_mgtq, m0); 1954173273Ssam if (m0 != NULL) { 1955173273Ssam if (sc->prioq.queued >= RT2560_PRIO_RING_COUNT) { 1956173273Ssam ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1957173273Ssam break; 1958173273Ssam } 1959173273Ssam IF_DEQUEUE(&ic->ic_mgtq, m0); 1960173273Ssam 1961178354Ssam ni = (struct ieee80211_node *)m0->m_pkthdr.rcvif; 1962173273Ssam m0->m_pkthdr.rcvif = NULL; 1963178354Ssam 1964173273Ssam if (bpf_peers_present(ic->ic_rawbpf)) 1965173273Ssam bpf_mtap(ic->ic_rawbpf, m0); 1966173273Ssam 1967173865Ssam if (rt2560_tx_mgt(sc, m0, ni) != 0) 1968173865Ssam break; 1969173865Ssam 1970173273Ssam } else { 1971173273Ssam if (ic->ic_state != IEEE80211_S_RUN) 1972178354Ssam break; 1973173273Ssam IFQ_DRV_DEQUEUE(&ifp->if_snd, m0); 1974173273Ssam if (m0 == NULL) 1975173273Ssam break; 1976178354Ssam if (sc->txq.queued >= RT2560_TX_RING_COUNT - 1) { 1977178354Ssam IFQ_DRV_PREPEND(&ifp->if_snd, m0); 1978173273Ssam ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1979170530Ssam break; 1980178354Ssam } 1981170530Ssam 1982178354Ssam if (m0->m_len < sizeof (struct ether_header) && 1983170530Ssam !(m0 = m_pullup(m0, sizeof (struct ether_header)))) 1984170530Ssam continue; 1985170530Ssam 1986170530Ssam eh = mtod(m0, struct ether_header *); 1987170530Ssam ni = ieee80211_find_txnode(ic, eh->ether_dhost); 1988173865Ssam if (ni == NULL) { 1989173865Ssam m_freem(m0); 1990173273Ssam continue; 1991170530Ssam } 1992170530Ssam BPF_MTAP(ifp, m0); 1993170530Ssam 1994170530Ssam m0 = ieee80211_encap(ic, m0, ni); 1995170530Ssam if (m0 == NULL) { 1996170530Ssam ieee80211_free_node(ni); 1997170530Ssam continue; 1998173273Ssam } 1999173273Ssam 2000173273Ssam if (bpf_peers_present(ic->ic_rawbpf)) 2001173273Ssam bpf_mtap(ic->ic_rawbpf, m0); 2002173273Ssam 2003173273Ssam if (rt2560_tx_data(sc, m0, ni) != 0) { 2004173273Ssam ieee80211_free_node(ni); 2005170530Ssam ifp->if_oerrors++; 2006170530Ssam break; 2007170530Ssam } 2008170530Ssam } 2009170530Ssam 2010170530Ssam sc->sc_tx_timer = 5; 2011170530Ssam ifp->if_timer = 1; 2012170530Ssam } 2013170530Ssam 2014170530Ssam RAL_UNLOCK(sc); 2015170530Ssam} 2016170530Ssam 2017170530Ssamstatic void 2018170530Ssamrt2560_watchdog(struct ifnet *ifp) 2019170530Ssam{ 2020170530Ssam struct rt2560_softc *sc = ifp->if_softc; 2021170530Ssam struct ieee80211com *ic = &sc->sc_ic; 2022170530Ssam 2023170530Ssam RAL_LOCK(sc); 2024170530Ssam 2025170530Ssam ifp->if_timer = 0; 2026170530Ssam 2027170530Ssam if (sc->sc_tx_timer > 0) { 2028170530Ssam if (--sc->sc_tx_timer == 0) { 2029170530Ssam device_printf(sc->sc_dev, "device timeout\n"); 2030170530Ssam rt2560_init(sc); 2031170530Ssam ifp->if_oerrors++; 2032170530Ssam RAL_UNLOCK(sc); 2033170530Ssam return; 2034170530Ssam } 2035170530Ssam ifp->if_timer = 1; 2036170530Ssam } 2037170530Ssam 2038170530Ssam ieee80211_watchdog(ic); 2039170530Ssam 2040170530Ssam RAL_UNLOCK(sc); 2041170530Ssam} 2042170530Ssam 2043170530Ssam/* 2044170530Ssam * This function allows for fast channel switching in monitor mode (used by 2045170530Ssam * net-mgmt/kismet). In IBSS mode, we must explicitly reset the interface to 2046170530Ssam * generate a new beacon frame. 2047170530Ssam */ 2048170530Ssamstatic int 2049170530Ssamrt2560_reset(struct ifnet *ifp) 2050170530Ssam{ 2051170530Ssam struct rt2560_softc *sc = ifp->if_softc; 2052170530Ssam struct ieee80211com *ic = &sc->sc_ic; 2053170530Ssam 2054170530Ssam if (ic->ic_opmode != IEEE80211_M_MONITOR) 2055170530Ssam return ENETRESET; 2056170530Ssam 2057170530Ssam rt2560_set_chan(sc, ic->ic_curchan); 2058170530Ssam 2059172211Ssam return 0; 2060172211Ssam} 2061172211Ssam 2062178354Ssamstatic int 2063172211Ssamrt2560_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 2064172211Ssam{ 2065172211Ssam struct rt2560_softc *sc = ifp->if_softc; 2066178354Ssam struct ieee80211com *ic = &sc->sc_ic; 2067178354Ssam int error = 0; 2068172211Ssam 2069172211Ssam RAL_LOCK(sc); 2070172211Ssam 2071172211Ssam switch (cmd) { 2072178354Ssam case SIOCSIFFLAGS: 2073172211Ssam if (ifp->if_flags & IFF_UP) { 2074178354Ssam if (ifp->if_drv_flags & IFF_DRV_RUNNING) 2075172211Ssam rt2560_update_promisc(sc); 2076178354Ssam else 2077172211Ssam rt2560_init(sc); 2078172211Ssam } else { 2079172211Ssam if (ifp->if_drv_flags & IFF_DRV_RUNNING) 2080178354Ssam rt2560_stop(sc); 2081172211Ssam } 2082172211Ssam break; 2083172211Ssam 2084172211Ssam default: 2085172211Ssam error = ieee80211_ioctl(ic, cmd, data); 2086172211Ssam } 2087172211Ssam 2088172211Ssam if (error == ENETRESET) { 2089172211Ssam if ((ifp->if_flags & IFF_UP) && 2090172211Ssam (ifp->if_drv_flags & IFF_DRV_RUNNING) && 2091170530Ssam (ic->ic_roaming != IEEE80211_ROAMING_MANUAL)) 2092173273Ssam rt2560_init(sc); 2093173273Ssam error = 0; 2094173273Ssam } 2095173273Ssam 2096170530Ssam RAL_UNLOCK(sc); 2097170530Ssam 2098170530Ssam return error; 2099170530Ssam} 2100170530Ssam 2101170530Ssamstatic void 2102170530Ssamrt2560_bbp_write(struct rt2560_softc *sc, uint8_t reg, uint8_t val) 2103170530Ssam{ 2104170530Ssam uint32_t tmp; 2105170530Ssam int ntries; 2106178354Ssam 2107170530Ssam for (ntries = 0; ntries < 100; ntries++) { 2108170530Ssam if (!(RAL_READ(sc, RT2560_BBPCSR) & RT2560_BBP_BUSY)) 2109178354Ssam break; 2110170530Ssam DELAY(1); 2111178354Ssam } 2112170530Ssam if (ntries == 100) { 2113170530Ssam device_printf(sc->sc_dev, "could not write to BBP\n"); 2114170530Ssam return; 2115178354Ssam } 2116170530Ssam 2117170530Ssam tmp = RT2560_BBP_WRITE | RT2560_BBP_BUSY | reg << 8 | val; 2118172211Ssam RAL_WRITE(sc, RT2560_BBPCSR, tmp); 2119170530Ssam 2120170530Ssam DPRINTFN(15, ("BBP R%u <- 0x%02x\n", reg, val)); 2121170530Ssam} 2122170530Ssam 2123170530Ssamstatic uint8_t 2124170530Ssamrt2560_bbp_read(struct rt2560_softc *sc, uint8_t reg) 2125170530Ssam{ 2126170530Ssam uint32_t val; 2127170530Ssam int ntries; 2128170530Ssam 2129170530Ssam val = RT2560_BBP_BUSY | reg << 8; 2130170530Ssam RAL_WRITE(sc, RT2560_BBPCSR, val); 2131170530Ssam 2132170530Ssam for (ntries = 0; ntries < 100; ntries++) { 2133170530Ssam val = RAL_READ(sc, RT2560_BBPCSR); 2134170530Ssam if (!(val & RT2560_BBP_BUSY)) 2135170530Ssam return val & 0xff; 2136170530Ssam DELAY(1); 2137170530Ssam } 2138170530Ssam 2139170530Ssam device_printf(sc->sc_dev, "could not read from BBP\n"); 2140170530Ssam return 0; 2141170530Ssam} 2142170530Ssam 2143170530Ssamstatic void 2144170530Ssamrt2560_rf_write(struct rt2560_softc *sc, uint8_t reg, uint32_t val) 2145170530Ssam{ 2146170530Ssam uint32_t tmp; 2147170530Ssam int ntries; 2148170530Ssam 2149170530Ssam for (ntries = 0; ntries < 100; ntries++) { 2150170530Ssam if (!(RAL_READ(sc, RT2560_RFCSR) & RT2560_RF_BUSY)) 2151170530Ssam break; 2152170530Ssam DELAY(1); 2153170530Ssam } 2154170530Ssam if (ntries == 100) { 2155 device_printf(sc->sc_dev, "could not write to RF\n"); 2156 return; 2157 } 2158 2159 tmp = RT2560_RF_BUSY | RT2560_RF_20BIT | (val & 0xfffff) << 2 | 2160 (reg & 0x3); 2161 RAL_WRITE(sc, RT2560_RFCSR, tmp); 2162 2163 /* remember last written value in sc */ 2164 sc->rf_regs[reg] = val; 2165 2166 DPRINTFN(15, ("RF R[%u] <- 0x%05x\n", reg & 0x3, val & 0xfffff)); 2167} 2168 2169static void 2170rt2560_set_chan(struct rt2560_softc *sc, struct ieee80211_channel *c) 2171{ 2172 struct ieee80211com *ic = &sc->sc_ic; 2173 uint8_t power, tmp; 2174 u_int i, chan; 2175 2176 chan = ieee80211_chan2ieee(ic, c); 2177 if (chan == 0 || chan == IEEE80211_CHAN_ANY) 2178 return; 2179 2180 if (IEEE80211_IS_CHAN_2GHZ(c)) 2181 power = min(sc->txpow[chan - 1], 31); 2182 else 2183 power = 31; 2184 2185 /* adjust txpower using ifconfig settings */ 2186 power -= (100 - ic->ic_txpowlimit) / 8; 2187 2188 DPRINTFN(2, ("setting channel to %u, txpower to %u\n", chan, power)); 2189 2190 switch (sc->rf_rev) { 2191 case RT2560_RF_2522: 2192 rt2560_rf_write(sc, RAL_RF1, 0x00814); 2193 rt2560_rf_write(sc, RAL_RF2, rt2560_rf2522_r2[chan - 1]); 2194 rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x00040); 2195 break; 2196 2197 case RT2560_RF_2523: 2198 rt2560_rf_write(sc, RAL_RF1, 0x08804); 2199 rt2560_rf_write(sc, RAL_RF2, rt2560_rf2523_r2[chan - 1]); 2200 rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x38044); 2201 rt2560_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286); 2202 break; 2203 2204 case RT2560_RF_2524: 2205 rt2560_rf_write(sc, RAL_RF1, 0x0c808); 2206 rt2560_rf_write(sc, RAL_RF2, rt2560_rf2524_r2[chan - 1]); 2207 rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x00040); 2208 rt2560_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286); 2209 break; 2210 2211 case RT2560_RF_2525: 2212 rt2560_rf_write(sc, RAL_RF1, 0x08808); 2213 rt2560_rf_write(sc, RAL_RF2, rt2560_rf2525_hi_r2[chan - 1]); 2214 rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x18044); 2215 rt2560_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286); 2216 2217 rt2560_rf_write(sc, RAL_RF1, 0x08808); 2218 rt2560_rf_write(sc, RAL_RF2, rt2560_rf2525_r2[chan - 1]); 2219 rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x18044); 2220 rt2560_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00280 : 0x00286); 2221 break; 2222 2223 case RT2560_RF_2525E: 2224 rt2560_rf_write(sc, RAL_RF1, 0x08808); 2225 rt2560_rf_write(sc, RAL_RF2, rt2560_rf2525e_r2[chan - 1]); 2226 rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x18044); 2227 rt2560_rf_write(sc, RAL_RF4, (chan == 14) ? 0x00286 : 0x00282); 2228 break; 2229 2230 case RT2560_RF_2526: 2231 rt2560_rf_write(sc, RAL_RF2, rt2560_rf2526_hi_r2[chan - 1]); 2232 rt2560_rf_write(sc, RAL_RF4, (chan & 1) ? 0x00386 : 0x00381); 2233 rt2560_rf_write(sc, RAL_RF1, 0x08804); 2234 2235 rt2560_rf_write(sc, RAL_RF2, rt2560_rf2526_r2[chan - 1]); 2236 rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x18044); 2237 rt2560_rf_write(sc, RAL_RF4, (chan & 1) ? 0x00386 : 0x00381); 2238 break; 2239 2240 /* dual-band RF */ 2241 case RT2560_RF_5222: 2242 for (i = 0; rt2560_rf5222[i].chan != chan; i++); 2243 2244 rt2560_rf_write(sc, RAL_RF1, rt2560_rf5222[i].r1); 2245 rt2560_rf_write(sc, RAL_RF2, rt2560_rf5222[i].r2); 2246 rt2560_rf_write(sc, RAL_RF3, power << 7 | 0x00040); 2247 rt2560_rf_write(sc, RAL_RF4, rt2560_rf5222[i].r4); 2248 break; 2249 } 2250 2251 if (ic->ic_state != IEEE80211_S_SCAN) { 2252 /* set Japan filter bit for channel 14 */ 2253 tmp = rt2560_bbp_read(sc, 70); 2254 2255 tmp &= ~RT2560_JAPAN_FILTER; 2256 if (chan == 14) 2257 tmp |= RT2560_JAPAN_FILTER; 2258 2259 rt2560_bbp_write(sc, 70, tmp); 2260 2261 /* clear CRC errors */ 2262 RAL_READ(sc, RT2560_CNT0); 2263 } 2264} 2265 2266#if 0 2267/* 2268 * Disable RF auto-tuning. 2269 */ 2270static void 2271rt2560_disable_rf_tune(struct rt2560_softc *sc) 2272{ 2273 uint32_t tmp; 2274 2275 if (sc->rf_rev != RT2560_RF_2523) { 2276 tmp = sc->rf_regs[RAL_RF1] & ~RAL_RF1_AUTOTUNE; 2277 rt2560_rf_write(sc, RAL_RF1, tmp); 2278 } 2279 2280 tmp = sc->rf_regs[RAL_RF3] & ~RAL_RF3_AUTOTUNE; 2281 rt2560_rf_write(sc, RAL_RF3, tmp); 2282 2283 DPRINTFN(2, ("disabling RF autotune\n")); 2284} 2285#endif 2286 2287/* 2288 * Refer to IEEE Std 802.11-1999 pp. 123 for more information on TSF 2289 * synchronization. 2290 */ 2291static void 2292rt2560_enable_tsf_sync(struct rt2560_softc *sc) 2293{ 2294 struct ieee80211com *ic = &sc->sc_ic; 2295 uint16_t logcwmin, preload; 2296 uint32_t tmp; 2297 2298 /* first, disable TSF synchronization */ 2299 RAL_WRITE(sc, RT2560_CSR14, 0); 2300 2301 tmp = 16 * ic->ic_bss->ni_intval; 2302 RAL_WRITE(sc, RT2560_CSR12, tmp); 2303 2304 RAL_WRITE(sc, RT2560_CSR13, 0); 2305 2306 logcwmin = 5; 2307 preload = (ic->ic_opmode == IEEE80211_M_STA) ? 384 : 1024; 2308 tmp = logcwmin << 16 | preload; 2309 RAL_WRITE(sc, RT2560_BCNOCSR, tmp); 2310 2311 /* finally, enable TSF synchronization */ 2312 tmp = RT2560_ENABLE_TSF | RT2560_ENABLE_TBCN; 2313 if (ic->ic_opmode == IEEE80211_M_STA) 2314 tmp |= RT2560_ENABLE_TSF_SYNC(1); 2315 else 2316 tmp |= RT2560_ENABLE_TSF_SYNC(2) | 2317 RT2560_ENABLE_BEACON_GENERATOR; 2318 RAL_WRITE(sc, RT2560_CSR14, tmp); 2319 2320 DPRINTF(("enabling TSF synchronization\n")); 2321} 2322 2323static void 2324rt2560_update_plcp(struct rt2560_softc *sc) 2325{ 2326 struct ieee80211com *ic = &sc->sc_ic; 2327 2328 /* no short preamble for 1Mbps */ 2329 RAL_WRITE(sc, RT2560_PLCP1MCSR, 0x00700400); 2330 2331 if (!(ic->ic_flags & IEEE80211_F_SHPREAMBLE)) { 2332 /* values taken from the reference driver */ 2333 RAL_WRITE(sc, RT2560_PLCP2MCSR, 0x00380401); 2334 RAL_WRITE(sc, RT2560_PLCP5p5MCSR, 0x00150402); 2335 RAL_WRITE(sc, RT2560_PLCP11MCSR, 0x000b8403); 2336 } else { 2337 /* same values as above or'ed 0x8 */ 2338 RAL_WRITE(sc, RT2560_PLCP2MCSR, 0x00380409); 2339 RAL_WRITE(sc, RT2560_PLCP5p5MCSR, 0x0015040a); 2340 RAL_WRITE(sc, RT2560_PLCP11MCSR, 0x000b840b); 2341 } 2342 2343 DPRINTF(("updating PLCP for %s preamble\n", 2344 (ic->ic_flags & IEEE80211_F_SHPREAMBLE) ? "short" : "long")); 2345} 2346 2347/* 2348 * This function can be called by ieee80211_set_shortslottime(). Refer to 2349 * IEEE Std 802.11-1999 pp. 85 to know how these values are computed. 2350 */ 2351static void 2352rt2560_update_slot(struct ifnet *ifp) 2353{ 2354 struct rt2560_softc *sc = ifp->if_softc; 2355 struct ieee80211com *ic = &sc->sc_ic; 2356 uint8_t slottime; 2357 uint16_t tx_sifs, tx_pifs, tx_difs, eifs; 2358 uint32_t tmp; 2359 2360 slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20; 2361 2362 /* update the MAC slot boundaries */ 2363 tx_sifs = RAL_SIFS - RT2560_TXRX_TURNAROUND; 2364 tx_pifs = tx_sifs + slottime; 2365 tx_difs = tx_sifs + 2 * slottime; 2366 eifs = (ic->ic_curmode == IEEE80211_MODE_11B) ? 364 : 60; 2367 2368 tmp = RAL_READ(sc, RT2560_CSR11); 2369 tmp = (tmp & ~0x1f00) | slottime << 8; 2370 RAL_WRITE(sc, RT2560_CSR11, tmp); 2371 2372 tmp = tx_pifs << 16 | tx_sifs; 2373 RAL_WRITE(sc, RT2560_CSR18, tmp); 2374 2375 tmp = eifs << 16 | tx_difs; 2376 RAL_WRITE(sc, RT2560_CSR19, tmp); 2377 2378 DPRINTF(("setting slottime to %uus\n", slottime)); 2379} 2380 2381static void 2382rt2560_set_basicrates(struct rt2560_softc *sc) 2383{ 2384 struct ieee80211com *ic = &sc->sc_ic; 2385 2386 /* update basic rate set */ 2387 if (ic->ic_curmode == IEEE80211_MODE_11B) { 2388 /* 11b basic rates: 1, 2Mbps */ 2389 RAL_WRITE(sc, RT2560_ARSP_PLCP_1, 0x3); 2390 } else if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) { 2391 /* 11a basic rates: 6, 12, 24Mbps */ 2392 RAL_WRITE(sc, RT2560_ARSP_PLCP_1, 0x150); 2393 } else { 2394 /* 11g basic rates: 1, 2, 5.5, 11, 6, 12, 24Mbps */ 2395 RAL_WRITE(sc, RT2560_ARSP_PLCP_1, 0x15f); 2396 } 2397} 2398 2399static void 2400rt2560_update_led(struct rt2560_softc *sc, int led1, int led2) 2401{ 2402 uint32_t tmp; 2403 2404 /* set ON period to 70ms and OFF period to 30ms */ 2405 tmp = led1 << 16 | led2 << 17 | 70 << 8 | 30; 2406 RAL_WRITE(sc, RT2560_LEDCSR, tmp); 2407} 2408 2409static void 2410rt2560_set_bssid(struct rt2560_softc *sc, uint8_t *bssid) 2411{ 2412 uint32_t tmp; 2413 2414 tmp = bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24; 2415 RAL_WRITE(sc, RT2560_CSR5, tmp); 2416 2417 tmp = bssid[4] | bssid[5] << 8; 2418 RAL_WRITE(sc, RT2560_CSR6, tmp); 2419 2420 DPRINTF(("setting BSSID to %6D\n", bssid, ":")); 2421} 2422 2423static void 2424rt2560_set_macaddr(struct rt2560_softc *sc, uint8_t *addr) 2425{ 2426 uint32_t tmp; 2427 2428 tmp = addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24; 2429 RAL_WRITE(sc, RT2560_CSR3, tmp); 2430 2431 tmp = addr[4] | addr[5] << 8; 2432 RAL_WRITE(sc, RT2560_CSR4, tmp); 2433 2434 DPRINTF(("setting MAC address to %6D\n", addr, ":")); 2435} 2436 2437static void 2438rt2560_get_macaddr(struct rt2560_softc *sc, uint8_t *addr) 2439{ 2440 uint32_t tmp; 2441 2442 tmp = RAL_READ(sc, RT2560_CSR3); 2443 addr[0] = tmp & 0xff; 2444 addr[1] = (tmp >> 8) & 0xff; 2445 addr[2] = (tmp >> 16) & 0xff; 2446 addr[3] = (tmp >> 24); 2447 2448 tmp = RAL_READ(sc, RT2560_CSR4); 2449 addr[4] = tmp & 0xff; 2450 addr[5] = (tmp >> 8) & 0xff; 2451} 2452 2453static void 2454rt2560_update_promisc(struct rt2560_softc *sc) 2455{ 2456 struct ifnet *ifp = sc->sc_ic.ic_ifp; 2457 uint32_t tmp; 2458 2459 tmp = RAL_READ(sc, RT2560_RXCSR0); 2460 2461 tmp &= ~RT2560_DROP_NOT_TO_ME; 2462 if (!(ifp->if_flags & IFF_PROMISC)) 2463 tmp |= RT2560_DROP_NOT_TO_ME; 2464 2465 RAL_WRITE(sc, RT2560_RXCSR0, tmp); 2466 2467 DPRINTF(("%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ? 2468 "entering" : "leaving")); 2469} 2470 2471static const char * 2472rt2560_get_rf(int rev) 2473{ 2474 switch (rev) { 2475 case RT2560_RF_2522: return "RT2522"; 2476 case RT2560_RF_2523: return "RT2523"; 2477 case RT2560_RF_2524: return "RT2524"; 2478 case RT2560_RF_2525: return "RT2525"; 2479 case RT2560_RF_2525E: return "RT2525e"; 2480 case RT2560_RF_2526: return "RT2526"; 2481 case RT2560_RF_5222: return "RT5222"; 2482 default: return "unknown"; 2483 } 2484} 2485 2486static void 2487rt2560_read_eeprom(struct rt2560_softc *sc) 2488{ 2489 uint16_t val; 2490 int i; 2491 2492 val = rt2560_eeprom_read(sc, RT2560_EEPROM_CONFIG0); 2493 sc->rf_rev = (val >> 11) & 0x7; 2494 sc->hw_radio = (val >> 10) & 0x1; 2495 sc->led_mode = (val >> 6) & 0x7; 2496 sc->rx_ant = (val >> 4) & 0x3; 2497 sc->tx_ant = (val >> 2) & 0x3; 2498 sc->nb_ant = val & 0x3; 2499 2500 /* read default values for BBP registers */ 2501 for (i = 0; i < 16; i++) { 2502 val = rt2560_eeprom_read(sc, RT2560_EEPROM_BBP_BASE + i); 2503 sc->bbp_prom[i].reg = val >> 8; 2504 sc->bbp_prom[i].val = val & 0xff; 2505 } 2506 2507 /* read Tx power for all b/g channels */ 2508 for (i = 0; i < 14 / 2; i++) { 2509 val = rt2560_eeprom_read(sc, RT2560_EEPROM_TXPOWER + i); 2510 sc->txpow[i * 2] = val >> 8; 2511 sc->txpow[i * 2 + 1] = val & 0xff; 2512 } 2513} 2514 2515static int 2516rt2560_bbp_init(struct rt2560_softc *sc) 2517{ 2518#define N(a) (sizeof (a) / sizeof ((a)[0])) 2519 int i, ntries; 2520 2521 /* wait for BBP to be ready */ 2522 for (ntries = 0; ntries < 100; ntries++) { 2523 if (rt2560_bbp_read(sc, RT2560_BBP_VERSION) != 0) 2524 break; 2525 DELAY(1); 2526 } 2527 if (ntries == 100) { 2528 device_printf(sc->sc_dev, "timeout waiting for BBP\n"); 2529 return EIO; 2530 } 2531 2532 /* initialize BBP registers to default values */ 2533 for (i = 0; i < N(rt2560_def_bbp); i++) { 2534 rt2560_bbp_write(sc, rt2560_def_bbp[i].reg, 2535 rt2560_def_bbp[i].val); 2536 } 2537#if 0 2538 /* initialize BBP registers to values stored in EEPROM */ 2539 for (i = 0; i < 16; i++) { 2540 if (sc->bbp_prom[i].reg == 0xff) 2541 continue; 2542 rt2560_bbp_write(sc, sc->bbp_prom[i].reg, sc->bbp_prom[i].val); 2543 } 2544#endif 2545 2546 return 0; 2547#undef N 2548} 2549 2550static void 2551rt2560_set_txantenna(struct rt2560_softc *sc, int antenna) 2552{ 2553 uint32_t tmp; 2554 uint8_t tx; 2555 2556 tx = rt2560_bbp_read(sc, RT2560_BBP_TX) & ~RT2560_BBP_ANTMASK; 2557 if (antenna == 1) 2558 tx |= RT2560_BBP_ANTA; 2559 else if (antenna == 2) 2560 tx |= RT2560_BBP_ANTB; 2561 else 2562 tx |= RT2560_BBP_DIVERSITY; 2563 2564 /* need to force I/Q flip for RF 2525e, 2526 and 5222 */ 2565 if (sc->rf_rev == RT2560_RF_2525E || sc->rf_rev == RT2560_RF_2526 || 2566 sc->rf_rev == RT2560_RF_5222) 2567 tx |= RT2560_BBP_FLIPIQ; 2568 2569 rt2560_bbp_write(sc, RT2560_BBP_TX, tx); 2570 2571 /* update values for CCK and OFDM in BBPCSR1 */ 2572 tmp = RAL_READ(sc, RT2560_BBPCSR1) & ~0x00070007; 2573 tmp |= (tx & 0x7) << 16 | (tx & 0x7); 2574 RAL_WRITE(sc, RT2560_BBPCSR1, tmp); 2575} 2576 2577static void 2578rt2560_set_rxantenna(struct rt2560_softc *sc, int antenna) 2579{ 2580 uint8_t rx; 2581 2582 rx = rt2560_bbp_read(sc, RT2560_BBP_RX) & ~RT2560_BBP_ANTMASK; 2583 if (antenna == 1) 2584 rx |= RT2560_BBP_ANTA; 2585 else if (antenna == 2) 2586 rx |= RT2560_BBP_ANTB; 2587 else 2588 rx |= RT2560_BBP_DIVERSITY; 2589 2590 /* need to force no I/Q flip for RF 2525e and 2526 */ 2591 if (sc->rf_rev == RT2560_RF_2525E || sc->rf_rev == RT2560_RF_2526) 2592 rx &= ~RT2560_BBP_FLIPIQ; 2593 2594 rt2560_bbp_write(sc, RT2560_BBP_RX, rx); 2595} 2596 2597static void 2598rt2560_init(void *priv) 2599{ 2600#define N(a) (sizeof (a) / sizeof ((a)[0])) 2601 struct rt2560_softc *sc = priv; 2602 struct ieee80211com *ic = &sc->sc_ic; 2603 struct ifnet *ifp = ic->ic_ifp; 2604 uint32_t tmp; 2605 int i; 2606 2607 RAL_LOCK(sc); 2608 2609 rt2560_stop(sc); 2610 2611 /* setup tx rings */ 2612 tmp = RT2560_PRIO_RING_COUNT << 24 | 2613 RT2560_ATIM_RING_COUNT << 16 | 2614 RT2560_TX_RING_COUNT << 8 | 2615 RT2560_TX_DESC_SIZE; 2616 2617 /* rings must be initialized in this exact order */ 2618 RAL_WRITE(sc, RT2560_TXCSR2, tmp); 2619 RAL_WRITE(sc, RT2560_TXCSR3, sc->txq.physaddr); 2620 RAL_WRITE(sc, RT2560_TXCSR5, sc->prioq.physaddr); 2621 RAL_WRITE(sc, RT2560_TXCSR4, sc->atimq.physaddr); 2622 RAL_WRITE(sc, RT2560_TXCSR6, sc->bcnq.physaddr); 2623 2624 /* setup rx ring */ 2625 tmp = RT2560_RX_RING_COUNT << 8 | RT2560_RX_DESC_SIZE; 2626 2627 RAL_WRITE(sc, RT2560_RXCSR1, tmp); 2628 RAL_WRITE(sc, RT2560_RXCSR2, sc->rxq.physaddr); 2629 2630 /* initialize MAC registers to default values */ 2631 for (i = 0; i < N(rt2560_def_mac); i++) 2632 RAL_WRITE(sc, rt2560_def_mac[i].reg, rt2560_def_mac[i].val); 2633 2634 IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp)); 2635 rt2560_set_macaddr(sc, ic->ic_myaddr); 2636 2637 /* set basic rate set (will be updated later) */ 2638 RAL_WRITE(sc, RT2560_ARSP_PLCP_1, 0x153); 2639 2640 rt2560_set_txantenna(sc, sc->tx_ant); 2641 rt2560_set_rxantenna(sc, sc->rx_ant); 2642 rt2560_update_slot(ifp); 2643 rt2560_update_plcp(sc); 2644 rt2560_update_led(sc, 0, 0); 2645 2646 RAL_WRITE(sc, RT2560_CSR1, RT2560_RESET_ASIC); 2647 RAL_WRITE(sc, RT2560_CSR1, RT2560_HOST_READY); 2648 2649 if (rt2560_bbp_init(sc) != 0) { 2650 rt2560_stop(sc); 2651 RAL_UNLOCK(sc); 2652 return; 2653 } 2654 2655 /* set default BSS channel */ 2656 rt2560_set_chan(sc, ic->ic_curchan); 2657 2658 /* kick Rx */ 2659 tmp = RT2560_DROP_PHY_ERROR | RT2560_DROP_CRC_ERROR; 2660 if (ic->ic_opmode != IEEE80211_M_MONITOR) { 2661 tmp |= RT2560_DROP_CTL | RT2560_DROP_VERSION_ERROR; 2662 if (ic->ic_opmode != IEEE80211_M_HOSTAP) 2663 tmp |= RT2560_DROP_TODS; 2664 if (!(ifp->if_flags & IFF_PROMISC)) 2665 tmp |= RT2560_DROP_NOT_TO_ME; 2666 } 2667 RAL_WRITE(sc, RT2560_RXCSR0, tmp); 2668 2669 /* clear old FCS and Rx FIFO errors */ 2670 RAL_READ(sc, RT2560_CNT0); 2671 RAL_READ(sc, RT2560_CNT4); 2672 2673 /* clear any pending interrupts */ 2674 RAL_WRITE(sc, RT2560_CSR7, 0xffffffff); 2675 2676 /* enable interrupts */ 2677 RAL_WRITE(sc, RT2560_CSR8, RT2560_INTR_MASK); 2678 2679 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 2680 ifp->if_drv_flags |= IFF_DRV_RUNNING; 2681 2682 if (ic->ic_opmode != IEEE80211_M_MONITOR) { 2683 if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL) 2684 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); 2685 } else 2686 ieee80211_new_state(ic, IEEE80211_S_RUN, -1); 2687 2688 RAL_UNLOCK(sc); 2689#undef N 2690} 2691 2692void 2693rt2560_stop(void *priv) 2694{ 2695 struct rt2560_softc *sc = priv; 2696 struct ieee80211com *ic = &sc->sc_ic; 2697 struct ifnet *ifp = ic->ic_ifp; 2698 2699 sc->sc_tx_timer = 0; 2700 ifp->if_timer = 0; 2701 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 2702 2703 ieee80211_new_state(ic, IEEE80211_S_INIT, -1); 2704 2705 /* abort Tx */ 2706 RAL_WRITE(sc, RT2560_TXCSR0, RT2560_ABORT_TX); 2707 2708 /* disable Rx */ 2709 RAL_WRITE(sc, RT2560_RXCSR0, RT2560_DISABLE_RX); 2710 2711 /* reset ASIC (imply reset BBP) */ 2712 RAL_WRITE(sc, RT2560_CSR1, RT2560_RESET_ASIC); 2713 RAL_WRITE(sc, RT2560_CSR1, 0); 2714 2715 /* disable interrupts */ 2716 RAL_WRITE(sc, RT2560_CSR8, 0xffffffff); 2717 2718 /* reset Tx and Rx rings */ 2719 rt2560_reset_tx_ring(sc, &sc->txq); 2720 rt2560_reset_tx_ring(sc, &sc->atimq); 2721 rt2560_reset_tx_ring(sc, &sc->prioq); 2722 rt2560_reset_tx_ring(sc, &sc->bcnq); 2723 rt2560_reset_rx_ring(sc, &sc->rxq); 2724} 2725