Annotation of sys/dev/ic/rt2661.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: rt2661.c,v 1.36 2007/03/08 18:50:57 deraadt Exp $ */
! 2:
! 3: /*-
! 4: * Copyright (c) 2006
! 5: * Damien Bergamini <damien.bergamini@free.fr>
! 6: *
! 7: * Permission to use, copy, modify, and distribute this software for any
! 8: * purpose with or without fee is hereby granted, provided that the above
! 9: * copyright notice and this permission notice appear in all copies.
! 10: *
! 11: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 12: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 13: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 14: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 15: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 16: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 17: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 18: */
! 19:
! 20: /*-
! 21: * Ralink Technology RT2561, RT2561S and RT2661 chipset driver
! 22: * http://www.ralinktech.com/
! 23: */
! 24:
! 25: #include "bpfilter.h"
! 26:
! 27: #include <sys/param.h>
! 28: #include <sys/sockio.h>
! 29: #include <sys/sysctl.h>
! 30: #include <sys/mbuf.h>
! 31: #include <sys/kernel.h>
! 32: #include <sys/socket.h>
! 33: #include <sys/systm.h>
! 34: #include <sys/malloc.h>
! 35: #include <sys/timeout.h>
! 36: #include <sys/conf.h>
! 37: #include <sys/device.h>
! 38:
! 39: #include <machine/bus.h>
! 40: #include <machine/endian.h>
! 41: #include <machine/intr.h>
! 42:
! 43: #if NBPFILTER > 0
! 44: #include <net/bpf.h>
! 45: #endif
! 46: #include <net/if.h>
! 47: #include <net/if_arp.h>
! 48: #include <net/if_dl.h>
! 49: #include <net/if_media.h>
! 50: #include <net/if_types.h>
! 51:
! 52: #include <netinet/in.h>
! 53: #include <netinet/in_systm.h>
! 54: #include <netinet/in_var.h>
! 55: #include <netinet/if_ether.h>
! 56: #include <netinet/ip.h>
! 57:
! 58: #include <net80211/ieee80211_var.h>
! 59: #include <net80211/ieee80211_amrr.h>
! 60: #include <net80211/ieee80211_radiotap.h>
! 61:
! 62: #include <dev/ic/rt2661reg.h>
! 63: #include <dev/ic/rt2661var.h>
! 64:
! 65: #include <dev/pci/pcireg.h>
! 66: #include <dev/pci/pcivar.h>
! 67: #include <dev/pci/pcidevs.h>
! 68:
! 69: #ifdef RAL_DEBUG
! 70: #define DPRINTF(x) do { if (rt2661_debug > 0) printf x; } while (0)
! 71: #define DPRINTFN(n, x) do { if (rt2661_debug >= (n)) printf x; } while (0)
! 72: int rt2661_debug = 1;
! 73: #else
! 74: #define DPRINTF(x)
! 75: #define DPRINTFN(n, x)
! 76: #endif
! 77:
! 78: int rt2661_alloc_tx_ring(struct rt2661_softc *,
! 79: struct rt2661_tx_ring *, int);
! 80: void rt2661_reset_tx_ring(struct rt2661_softc *,
! 81: struct rt2661_tx_ring *);
! 82: void rt2661_free_tx_ring(struct rt2661_softc *,
! 83: struct rt2661_tx_ring *);
! 84: int rt2661_alloc_rx_ring(struct rt2661_softc *,
! 85: struct rt2661_rx_ring *, int);
! 86: void rt2661_reset_rx_ring(struct rt2661_softc *,
! 87: struct rt2661_rx_ring *);
! 88: void rt2661_free_rx_ring(struct rt2661_softc *,
! 89: struct rt2661_rx_ring *);
! 90: struct ieee80211_node *rt2661_node_alloc(struct ieee80211com *);
! 91: int rt2661_media_change(struct ifnet *);
! 92: void rt2661_next_scan(void *);
! 93: void rt2661_iter_func(void *, struct ieee80211_node *);
! 94: void rt2661_updatestats(void *);
! 95: void rt2661_newassoc(struct ieee80211com *, struct ieee80211_node *,
! 96: int);
! 97: int rt2661_newstate(struct ieee80211com *, enum ieee80211_state,
! 98: int);
! 99: uint16_t rt2661_eeprom_read(struct rt2661_softc *, uint8_t);
! 100: void rt2661_tx_intr(struct rt2661_softc *);
! 101: void rt2661_tx_dma_intr(struct rt2661_softc *,
! 102: struct rt2661_tx_ring *);
! 103: void rt2661_rx_intr(struct rt2661_softc *);
! 104: void rt2661_mcu_beacon_expire(struct rt2661_softc *);
! 105: void rt2661_mcu_wakeup(struct rt2661_softc *);
! 106: void rt2661_mcu_cmd_intr(struct rt2661_softc *);
! 107: int rt2661_intr(void *);
! 108: #if NBPFILTER > 0
! 109: uint8_t rt2661_rxrate(const struct rt2661_rx_desc *);
! 110: #endif
! 111: int rt2661_ack_rate(struct ieee80211com *, int);
! 112: uint16_t rt2661_txtime(int, int, uint32_t);
! 113: uint8_t rt2661_plcp_signal(int);
! 114: void rt2661_setup_tx_desc(struct rt2661_softc *,
! 115: struct rt2661_tx_desc *, uint32_t, uint16_t, int, int,
! 116: const bus_dma_segment_t *, int, int);
! 117: int rt2661_tx_mgt(struct rt2661_softc *, struct mbuf *,
! 118: struct ieee80211_node *);
! 119: int rt2661_tx_data(struct rt2661_softc *, struct mbuf *,
! 120: struct ieee80211_node *, int);
! 121: void rt2661_start(struct ifnet *);
! 122: void rt2661_watchdog(struct ifnet *);
! 123: int rt2661_ioctl(struct ifnet *, u_long, caddr_t);
! 124: void rt2661_bbp_write(struct rt2661_softc *, uint8_t, uint8_t);
! 125: uint8_t rt2661_bbp_read(struct rt2661_softc *, uint8_t);
! 126: void rt2661_rf_write(struct rt2661_softc *, uint8_t, uint32_t);
! 127: int rt2661_tx_cmd(struct rt2661_softc *, uint8_t, uint16_t);
! 128: void rt2661_select_antenna(struct rt2661_softc *);
! 129: void rt2661_enable_mrr(struct rt2661_softc *);
! 130: void rt2661_set_txpreamble(struct rt2661_softc *);
! 131: void rt2661_set_basicrates(struct rt2661_softc *);
! 132: void rt2661_select_band(struct rt2661_softc *,
! 133: struct ieee80211_channel *);
! 134: void rt2661_set_chan(struct rt2661_softc *,
! 135: struct ieee80211_channel *);
! 136: void rt2661_set_bssid(struct rt2661_softc *, const uint8_t *);
! 137: void rt2661_set_macaddr(struct rt2661_softc *, const uint8_t *);
! 138: void rt2661_update_promisc(struct rt2661_softc *);
! 139: void rt2661_updateslot(struct ieee80211com *);
! 140: void rt2661_set_slottime(struct rt2661_softc *);
! 141: const char *rt2661_get_rf(int);
! 142: void rt2661_read_eeprom(struct rt2661_softc *);
! 143: int rt2661_bbp_init(struct rt2661_softc *);
! 144: int rt2661_init(struct ifnet *);
! 145: void rt2661_stop(struct ifnet *, int);
! 146: int rt2661_load_microcode(struct rt2661_softc *, const uint8_t *,
! 147: int);
! 148: void rt2661_rx_tune(struct rt2661_softc *);
! 149: #ifdef notyet
! 150: void rt2661_radar_start(struct rt2661_softc *);
! 151: int rt2661_radar_stop(struct rt2661_softc *);
! 152: #endif
! 153: int rt2661_prepare_beacon(struct rt2661_softc *);
! 154: void rt2661_enable_tsf_sync(struct rt2661_softc *);
! 155: int rt2661_get_rssi(struct rt2661_softc *, uint8_t);
! 156: void rt2661_power(int, void *);
! 157: void rt2661_shutdown(void *);
! 158:
! 159: static const struct {
! 160: uint32_t reg;
! 161: uint32_t val;
! 162: } rt2661_def_mac[] = {
! 163: RT2661_DEF_MAC
! 164: };
! 165:
! 166: static const struct {
! 167: uint8_t reg;
! 168: uint8_t val;
! 169: } rt2661_def_bbp[] = {
! 170: RT2661_DEF_BBP
! 171: };
! 172:
! 173: static const struct rfprog {
! 174: uint8_t chan;
! 175: uint32_t r1, r2, r3, r4;
! 176: } rt2661_rf5225_1[] = {
! 177: RT2661_RF5225_1
! 178: }, rt2661_rf5225_2[] = {
! 179: RT2661_RF5225_2
! 180: };
! 181:
! 182: int
! 183: rt2661_attach(void *xsc, int id)
! 184: {
! 185: struct rt2661_softc *sc = xsc;
! 186: struct ieee80211com *ic = &sc->sc_ic;
! 187: struct ifnet *ifp = &ic->ic_if;
! 188: uint32_t val;
! 189: int error, ac, i, ntries;
! 190:
! 191: sc->sc_id = id;
! 192:
! 193: sc->amrr.amrr_min_success_threshold = 1;
! 194: sc->amrr.amrr_max_success_threshold = 15;
! 195: timeout_set(&sc->amrr_to, rt2661_updatestats, sc);
! 196: timeout_set(&sc->scan_to, rt2661_next_scan, sc);
! 197:
! 198: /* wait for NIC to initialize */
! 199: for (ntries = 0; ntries < 1000; ntries++) {
! 200: if ((val = RAL_READ(sc, RT2661_MAC_CSR0)) != 0)
! 201: break;
! 202: DELAY(1000);
! 203: }
! 204: if (ntries == 1000) {
! 205: printf("%s: timeout waiting for NIC to initialize\n",
! 206: sc->sc_dev.dv_xname);
! 207: return EIO;
! 208: }
! 209:
! 210: /* retrieve RF rev. no and various other things from EEPROM */
! 211: rt2661_read_eeprom(sc);
! 212: printf(", address %s\n", ether_sprintf(ic->ic_myaddr));
! 213:
! 214: printf("%s: MAC/BBP RT%X, RF %s\n", sc->sc_dev.dv_xname, val,
! 215: rt2661_get_rf(sc->rf_rev));
! 216:
! 217: /*
! 218: * Allocate Tx and Rx rings.
! 219: */
! 220: for (ac = 0; ac < 4; ac++) {
! 221: error = rt2661_alloc_tx_ring(sc, &sc->txq[ac],
! 222: RT2661_TX_RING_COUNT);
! 223: if (error != 0) {
! 224: printf("%s: could not allocate Tx ring %d\n",
! 225: sc->sc_dev.dv_xname, ac);
! 226: goto fail1;
! 227: }
! 228: }
! 229:
! 230: error = rt2661_alloc_tx_ring(sc, &sc->mgtq, RT2661_MGT_RING_COUNT);
! 231: if (error != 0) {
! 232: printf("%s: could not allocate Mgt ring\n",
! 233: sc->sc_dev.dv_xname);
! 234: goto fail1;
! 235: }
! 236:
! 237: error = rt2661_alloc_rx_ring(sc, &sc->rxq, RT2661_RX_RING_COUNT);
! 238: if (error != 0) {
! 239: printf("%s: could not allocate Rx ring\n",
! 240: sc->sc_dev.dv_xname);
! 241: goto fail2;
! 242: }
! 243:
! 244: ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
! 245: ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
! 246: ic->ic_state = IEEE80211_S_INIT;
! 247:
! 248: /* set device capabilities */
! 249: ic->ic_caps =
! 250: IEEE80211_C_IBSS | /* IBSS mode supported */
! 251: IEEE80211_C_MONITOR | /* monitor mode supported */
! 252: IEEE80211_C_HOSTAP | /* HostAP mode supported */
! 253: IEEE80211_C_TXPMGT | /* tx power management */
! 254: IEEE80211_C_SHPREAMBLE | /* short preamble supported */
! 255: IEEE80211_C_SHSLOT | /* short slot time supported */
! 256: IEEE80211_C_WEP; /* s/w WEP */
! 257:
! 258: if (sc->rf_rev == RT2661_RF_5225 || sc->rf_rev == RT2661_RF_5325) {
! 259: /* set supported .11a rates */
! 260: ic->ic_sup_rates[IEEE80211_MODE_11A] =
! 261: ieee80211_std_rateset_11a;
! 262:
! 263: /* set supported .11a channels */
! 264: for (i = 36; i <= 64; i += 4) {
! 265: ic->ic_channels[i].ic_freq =
! 266: ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
! 267: ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
! 268: }
! 269: for (i = 100; i <= 140; i += 4) {
! 270: ic->ic_channels[i].ic_freq =
! 271: ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
! 272: ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
! 273: }
! 274: for (i = 149; i <= 165; i += 4) {
! 275: ic->ic_channels[i].ic_freq =
! 276: ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
! 277: ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
! 278: }
! 279: }
! 280:
! 281: /* set supported .11b and .11g rates */
! 282: ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
! 283: ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
! 284:
! 285: /* set supported .11b and .11g channels (1 through 14) */
! 286: for (i = 1; i <= 14; i++) {
! 287: ic->ic_channels[i].ic_freq =
! 288: ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
! 289: ic->ic_channels[i].ic_flags =
! 290: IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
! 291: IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
! 292: }
! 293:
! 294: ifp->if_softc = sc;
! 295: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
! 296: ifp->if_init = rt2661_init;
! 297: ifp->if_ioctl = rt2661_ioctl;
! 298: ifp->if_start = rt2661_start;
! 299: ifp->if_watchdog = rt2661_watchdog;
! 300: IFQ_SET_READY(&ifp->if_snd);
! 301: memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
! 302:
! 303: if_attach(ifp);
! 304: ieee80211_ifattach(ifp);
! 305: ic->ic_node_alloc = rt2661_node_alloc;
! 306: ic->ic_newassoc = rt2661_newassoc;
! 307: ic->ic_updateslot = rt2661_updateslot;
! 308:
! 309: /* override state transition machine */
! 310: sc->sc_newstate = ic->ic_newstate;
! 311: ic->ic_newstate = rt2661_newstate;
! 312: ieee80211_media_init(ifp, rt2661_media_change, ieee80211_media_status);
! 313:
! 314: #if NBPFILTER > 0
! 315: bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO,
! 316: sizeof (struct ieee80211_frame) + 64);
! 317:
! 318: sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
! 319: sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
! 320: sc->sc_rxtap.wr_ihdr.it_present = htole32(RT2661_RX_RADIOTAP_PRESENT);
! 321:
! 322: sc->sc_txtap_len = sizeof sc->sc_txtapu;
! 323: sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
! 324: sc->sc_txtap.wt_ihdr.it_present = htole32(RT2661_TX_RADIOTAP_PRESENT);
! 325: #endif
! 326:
! 327: /*
! 328: * Make sure the interface is shutdown during reboot.
! 329: */
! 330: sc->sc_sdhook = shutdownhook_establish(rt2661_shutdown, sc);
! 331: if (sc->sc_sdhook == NULL) {
! 332: printf("%s: WARNING: unable to establish shutdown hook\n",
! 333: sc->sc_dev.dv_xname);
! 334: }
! 335: sc->sc_powerhook = powerhook_establish(rt2661_power, sc);
! 336: if (sc->sc_powerhook == NULL) {
! 337: printf("%s: WARNING: unable to establish power hook\n",
! 338: sc->sc_dev.dv_xname);
! 339: }
! 340:
! 341: return 0;
! 342:
! 343: fail2: rt2661_free_tx_ring(sc, &sc->mgtq);
! 344: fail1: while (--ac >= 0)
! 345: rt2661_free_tx_ring(sc, &sc->txq[ac]);
! 346: return ENXIO;
! 347: }
! 348:
! 349: int
! 350: rt2661_detach(void *xsc)
! 351: {
! 352: struct rt2661_softc *sc = xsc;
! 353: struct ifnet *ifp = &sc->sc_ic.ic_if;
! 354: int ac;
! 355:
! 356: timeout_del(&sc->scan_to);
! 357: timeout_del(&sc->amrr_to);
! 358:
! 359: ieee80211_ifdetach(ifp); /* free all nodes */
! 360: if_detach(ifp);
! 361:
! 362: if (sc->sc_powerhook != NULL)
! 363: powerhook_disestablish(sc->sc_powerhook);
! 364: if (sc->sc_sdhook != NULL)
! 365: shutdownhook_disestablish(sc->sc_sdhook);
! 366:
! 367: for (ac = 0; ac < 4; ac++)
! 368: rt2661_free_tx_ring(sc, &sc->txq[ac]);
! 369: rt2661_free_tx_ring(sc, &sc->mgtq);
! 370: rt2661_free_rx_ring(sc, &sc->rxq);
! 371:
! 372: return 0;
! 373: }
! 374:
! 375: int
! 376: rt2661_alloc_tx_ring(struct rt2661_softc *sc, struct rt2661_tx_ring *ring,
! 377: int count)
! 378: {
! 379: int i, nsegs, error;
! 380:
! 381: ring->count = count;
! 382: ring->queued = 0;
! 383: ring->cur = ring->next = ring->stat = 0;
! 384:
! 385: error = bus_dmamap_create(sc->sc_dmat, count * RT2661_TX_DESC_SIZE, 1,
! 386: count * RT2661_TX_DESC_SIZE, 0, BUS_DMA_NOWAIT, &ring->map);
! 387: if (error != 0) {
! 388: printf("%s: could not create desc DMA map\n",
! 389: sc->sc_dev.dv_xname);
! 390: goto fail;
! 391: }
! 392:
! 393: error = bus_dmamem_alloc(sc->sc_dmat, count * RT2661_TX_DESC_SIZE,
! 394: PAGE_SIZE, 0, &ring->seg, 1, &nsegs, BUS_DMA_NOWAIT);
! 395: if (error != 0) {
! 396: printf("%s: could not allocate DMA memory\n",
! 397: sc->sc_dev.dv_xname);
! 398: goto fail;
! 399: }
! 400:
! 401: error = bus_dmamem_map(sc->sc_dmat, &ring->seg, nsegs,
! 402: count * RT2661_TX_DESC_SIZE, (caddr_t *)&ring->desc,
! 403: BUS_DMA_NOWAIT);
! 404: if (error != 0) {
! 405: printf("%s: could not map desc DMA memory\n",
! 406: sc->sc_dev.dv_xname);
! 407: goto fail;
! 408: }
! 409:
! 410: error = bus_dmamap_load(sc->sc_dmat, ring->map, ring->desc,
! 411: count * RT2661_TX_DESC_SIZE, NULL, BUS_DMA_NOWAIT);
! 412: if (error != 0) {
! 413: printf("%s: could not load desc DMA map\n",
! 414: sc->sc_dev.dv_xname);
! 415: goto fail;
! 416: }
! 417:
! 418: memset(ring->desc, 0, count * RT2661_TX_DESC_SIZE);
! 419: ring->physaddr = ring->map->dm_segs->ds_addr;
! 420:
! 421: ring->data = malloc(count * sizeof (struct rt2661_tx_data), M_DEVBUF,
! 422: M_NOWAIT);
! 423: if (ring->data == NULL) {
! 424: printf("%s: could not allocate soft data\n",
! 425: sc->sc_dev.dv_xname);
! 426: error = ENOMEM;
! 427: goto fail;
! 428: }
! 429:
! 430: memset(ring->data, 0, count * sizeof (struct rt2661_tx_data));
! 431: for (i = 0; i < count; i++) {
! 432: error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
! 433: RT2661_MAX_SCATTER, MCLBYTES, 0, BUS_DMA_NOWAIT,
! 434: &ring->data[i].map);
! 435: if (error != 0) {
! 436: printf("%s: could not create DMA map\n",
! 437: sc->sc_dev.dv_xname);
! 438: goto fail;
! 439: }
! 440: }
! 441:
! 442: return 0;
! 443:
! 444: fail: rt2661_free_tx_ring(sc, ring);
! 445: return error;
! 446: }
! 447:
! 448: void
! 449: rt2661_reset_tx_ring(struct rt2661_softc *sc, struct rt2661_tx_ring *ring)
! 450: {
! 451: int i;
! 452:
! 453: for (i = 0; i < ring->count; i++) {
! 454: struct rt2661_tx_desc *desc = &ring->desc[i];
! 455: struct rt2661_tx_data *data = &ring->data[i];
! 456:
! 457: if (data->m != NULL) {
! 458: bus_dmamap_sync(sc->sc_dmat, data->map, 0,
! 459: data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
! 460: bus_dmamap_unload(sc->sc_dmat, data->map);
! 461: m_freem(data->m);
! 462: data->m = NULL;
! 463: }
! 464:
! 465: /*
! 466: * The node has already been freed at that point so don't call
! 467: * ieee80211_release_node() here.
! 468: */
! 469: data->ni = NULL;
! 470:
! 471: desc->flags = 0;
! 472: }
! 473:
! 474: bus_dmamap_sync(sc->sc_dmat, ring->map, 0, ring->map->dm_mapsize,
! 475: BUS_DMASYNC_PREWRITE);
! 476:
! 477: ring->queued = 0;
! 478: ring->cur = ring->next = ring->stat = 0;
! 479: }
! 480:
! 481: void
! 482: rt2661_free_tx_ring(struct rt2661_softc *sc, struct rt2661_tx_ring *ring)
! 483: {
! 484: int i;
! 485:
! 486: if (ring->desc != NULL) {
! 487: bus_dmamap_sync(sc->sc_dmat, ring->map, 0,
! 488: ring->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
! 489: bus_dmamap_unload(sc->sc_dmat, ring->map);
! 490: bus_dmamem_unmap(sc->sc_dmat, (caddr_t)ring->desc,
! 491: ring->count * RT2661_TX_DESC_SIZE);
! 492: bus_dmamem_free(sc->sc_dmat, &ring->seg, 1);
! 493: }
! 494:
! 495: if (ring->data != NULL) {
! 496: for (i = 0; i < ring->count; i++) {
! 497: struct rt2661_tx_data *data = &ring->data[i];
! 498:
! 499: if (data->m != NULL) {
! 500: bus_dmamap_sync(sc->sc_dmat, data->map, 0,
! 501: data->map->dm_mapsize,
! 502: BUS_DMASYNC_POSTWRITE);
! 503: bus_dmamap_unload(sc->sc_dmat, data->map);
! 504: m_freem(data->m);
! 505: }
! 506: /*
! 507: * The node has already been freed at that point so
! 508: * don't call ieee80211_release_node() here.
! 509: */
! 510: data->ni = NULL;
! 511:
! 512: if (data->map != NULL)
! 513: bus_dmamap_destroy(sc->sc_dmat, data->map);
! 514: }
! 515: free(ring->data, M_DEVBUF);
! 516: }
! 517: }
! 518:
! 519: int
! 520: rt2661_alloc_rx_ring(struct rt2661_softc *sc, struct rt2661_rx_ring *ring,
! 521: int count)
! 522: {
! 523: int i, nsegs, error;
! 524:
! 525: ring->count = count;
! 526: ring->cur = ring->next = 0;
! 527:
! 528: error = bus_dmamap_create(sc->sc_dmat, count * RT2661_RX_DESC_SIZE, 1,
! 529: count * RT2661_RX_DESC_SIZE, 0, BUS_DMA_NOWAIT, &ring->map);
! 530: if (error != 0) {
! 531: printf("%s: could not create desc DMA map\n",
! 532: sc->sc_dev.dv_xname);
! 533: goto fail;
! 534: }
! 535:
! 536: error = bus_dmamem_alloc(sc->sc_dmat, count * RT2661_RX_DESC_SIZE,
! 537: PAGE_SIZE, 0, &ring->seg, 1, &nsegs, BUS_DMA_NOWAIT);
! 538: if (error != 0) {
! 539: printf("%s: could not allocate DMA memory\n",
! 540: sc->sc_dev.dv_xname);
! 541: goto fail;
! 542: }
! 543:
! 544: error = bus_dmamem_map(sc->sc_dmat, &ring->seg, nsegs,
! 545: count * RT2661_RX_DESC_SIZE, (caddr_t *)&ring->desc,
! 546: BUS_DMA_NOWAIT);
! 547: if (error != 0) {
! 548: printf("%s: could not map desc DMA memory\n",
! 549: sc->sc_dev.dv_xname);
! 550: goto fail;
! 551: }
! 552:
! 553: error = bus_dmamap_load(sc->sc_dmat, ring->map, ring->desc,
! 554: count * RT2661_RX_DESC_SIZE, NULL, BUS_DMA_NOWAIT);
! 555: if (error != 0) {
! 556: printf("%s: could not load desc DMA map\n",
! 557: sc->sc_dev.dv_xname);
! 558: goto fail;
! 559: }
! 560:
! 561: memset(ring->desc, 0, count * RT2661_RX_DESC_SIZE);
! 562: ring->physaddr = ring->map->dm_segs->ds_addr;
! 563:
! 564: ring->data = malloc(count * sizeof (struct rt2661_rx_data), M_DEVBUF,
! 565: M_NOWAIT);
! 566: if (ring->data == NULL) {
! 567: printf("%s: could not allocate soft data\n",
! 568: sc->sc_dev.dv_xname);
! 569: error = ENOMEM;
! 570: goto fail;
! 571: }
! 572:
! 573: /*
! 574: * Pre-allocate Rx buffers and populate Rx ring.
! 575: */
! 576: memset(ring->data, 0, count * sizeof (struct rt2661_rx_data));
! 577: for (i = 0; i < count; i++) {
! 578: struct rt2661_rx_desc *desc = &sc->rxq.desc[i];
! 579: struct rt2661_rx_data *data = &sc->rxq.data[i];
! 580:
! 581: error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES,
! 582: 0, BUS_DMA_NOWAIT, &data->map);
! 583: if (error != 0) {
! 584: printf("%s: could not create DMA map\n",
! 585: sc->sc_dev.dv_xname);
! 586: goto fail;
! 587: }
! 588:
! 589: MGETHDR(data->m, M_DONTWAIT, MT_DATA);
! 590: if (data->m == NULL) {
! 591: printf("%s: could not allocate rx mbuf\n",
! 592: sc->sc_dev.dv_xname);
! 593: error = ENOMEM;
! 594: goto fail;
! 595: }
! 596: MCLGET(data->m, M_DONTWAIT);
! 597: if (!(data->m->m_flags & M_EXT)) {
! 598: printf("%s: could not allocate rx mbuf cluster\n",
! 599: sc->sc_dev.dv_xname);
! 600: error = ENOMEM;
! 601: goto fail;
! 602: }
! 603:
! 604: error = bus_dmamap_load(sc->sc_dmat, data->map,
! 605: mtod(data->m, void *), MCLBYTES, NULL, BUS_DMA_NOWAIT);
! 606: if (error != 0) {
! 607: printf("%s: could not load rx buf DMA map",
! 608: sc->sc_dev.dv_xname);
! 609: goto fail;
! 610: }
! 611:
! 612: desc->flags = htole32(RT2661_RX_BUSY);
! 613: desc->physaddr = htole32(data->map->dm_segs->ds_addr);
! 614: }
! 615:
! 616: bus_dmamap_sync(sc->sc_dmat, ring->map, 0, ring->map->dm_mapsize,
! 617: BUS_DMASYNC_PREWRITE);
! 618:
! 619: return 0;
! 620:
! 621: fail: rt2661_free_rx_ring(sc, ring);
! 622: return error;
! 623: }
! 624:
! 625: void
! 626: rt2661_reset_rx_ring(struct rt2661_softc *sc, struct rt2661_rx_ring *ring)
! 627: {
! 628: int i;
! 629:
! 630: for (i = 0; i < ring->count; i++)
! 631: ring->desc[i].flags = htole32(RT2661_RX_BUSY);
! 632:
! 633: bus_dmamap_sync(sc->sc_dmat, ring->map, 0, ring->map->dm_mapsize,
! 634: BUS_DMASYNC_PREWRITE);
! 635:
! 636: ring->cur = ring->next = 0;
! 637: }
! 638:
! 639: void
! 640: rt2661_free_rx_ring(struct rt2661_softc *sc, struct rt2661_rx_ring *ring)
! 641: {
! 642: int i;
! 643:
! 644: if (ring->desc != NULL) {
! 645: bus_dmamap_sync(sc->sc_dmat, ring->map, 0,
! 646: ring->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
! 647: bus_dmamap_unload(sc->sc_dmat, ring->map);
! 648: bus_dmamem_unmap(sc->sc_dmat, (caddr_t)ring->desc,
! 649: ring->count * RT2661_RX_DESC_SIZE);
! 650: bus_dmamem_free(sc->sc_dmat, &ring->seg, 1);
! 651: }
! 652:
! 653: if (ring->data != NULL) {
! 654: for (i = 0; i < ring->count; i++) {
! 655: struct rt2661_rx_data *data = &ring->data[i];
! 656:
! 657: if (data->m != NULL) {
! 658: bus_dmamap_sync(sc->sc_dmat, data->map, 0,
! 659: data->map->dm_mapsize,
! 660: BUS_DMASYNC_POSTREAD);
! 661: bus_dmamap_unload(sc->sc_dmat, data->map);
! 662: m_freem(data->m);
! 663: }
! 664:
! 665: if (data->map != NULL)
! 666: bus_dmamap_destroy(sc->sc_dmat, data->map);
! 667: }
! 668: free(ring->data, M_DEVBUF);
! 669: }
! 670: }
! 671:
! 672: struct ieee80211_node *
! 673: rt2661_node_alloc(struct ieee80211com *ic)
! 674: {
! 675: struct rt2661_node *rn;
! 676:
! 677: rn = malloc(sizeof (struct rt2661_node), M_DEVBUF, M_NOWAIT);
! 678: if (rn != NULL)
! 679: bzero(rn, sizeof (struct rt2661_node));
! 680: return (struct ieee80211_node *)rn;
! 681: }
! 682:
! 683: int
! 684: rt2661_media_change(struct ifnet *ifp)
! 685: {
! 686: int error;
! 687:
! 688: error = ieee80211_media_change(ifp);
! 689: if (error != ENETRESET)
! 690: return error;
! 691:
! 692: if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
! 693: rt2661_init(ifp);
! 694:
! 695: return 0;
! 696: }
! 697:
! 698: /*
! 699: * This function is called periodically (every 200ms) during scanning to
! 700: * switch from one channel to another.
! 701: */
! 702: void
! 703: rt2661_next_scan(void *arg)
! 704: {
! 705: struct rt2661_softc *sc = arg;
! 706: struct ieee80211com *ic = &sc->sc_ic;
! 707: struct ifnet *ifp = &ic->ic_if;
! 708: int s;
! 709:
! 710: s = splnet();
! 711: if (ic->ic_state == IEEE80211_S_SCAN)
! 712: ieee80211_next_scan(ifp);
! 713: splx(s);
! 714: }
! 715:
! 716: /*
! 717: * This function is called for each neighbor node.
! 718: */
! 719: void
! 720: rt2661_iter_func(void *arg, struct ieee80211_node *ni)
! 721: {
! 722: struct rt2661_softc *sc = arg;
! 723: struct rt2661_node *rn = (struct rt2661_node *)ni;
! 724:
! 725: ieee80211_amrr_choose(&sc->amrr, ni, &rn->amn);
! 726: }
! 727:
! 728: /*
! 729: * This function is called periodically (every 500ms) in RUN state to update
! 730: * various settings like rate control statistics or Rx sensitivity.
! 731: */
! 732: void
! 733: rt2661_updatestats(void *arg)
! 734: {
! 735: struct rt2661_softc *sc = arg;
! 736: struct ieee80211com *ic = &sc->sc_ic;
! 737: int s;
! 738:
! 739: s = splnet();
! 740: if (ic->ic_opmode == IEEE80211_M_STA)
! 741: rt2661_iter_func(sc, ic->ic_bss);
! 742: else
! 743: ieee80211_iterate_nodes(ic, rt2661_iter_func, arg);
! 744:
! 745: /* update rx sensitivity every 1 sec */
! 746: if (++sc->ncalls & 1)
! 747: rt2661_rx_tune(sc);
! 748: splx(s);
! 749:
! 750: timeout_add(&sc->amrr_to, hz / 2);
! 751: }
! 752:
! 753: void
! 754: rt2661_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
! 755: {
! 756: struct rt2661_softc *sc = ic->ic_softc;
! 757: int i;
! 758:
! 759: ieee80211_amrr_node_init(&sc->amrr, &((struct rt2661_node *)ni)->amn);
! 760:
! 761: /* set rate to some reasonable initial value */
! 762: for (i = ni->ni_rates.rs_nrates - 1;
! 763: i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL) > 72;
! 764: i--);
! 765: ni->ni_txrate = i;
! 766: }
! 767:
! 768: int
! 769: rt2661_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
! 770: {
! 771: struct rt2661_softc *sc = ic->ic_if.if_softc;
! 772: enum ieee80211_state ostate;
! 773: struct ieee80211_node *ni;
! 774: uint32_t tmp;
! 775: int error = 0;
! 776:
! 777: ostate = ic->ic_state;
! 778: timeout_del(&sc->scan_to);
! 779: timeout_del(&sc->amrr_to);
! 780:
! 781: switch (nstate) {
! 782: case IEEE80211_S_INIT:
! 783: if (ostate == IEEE80211_S_RUN) {
! 784: /* abort TSF synchronization */
! 785: tmp = RAL_READ(sc, RT2661_TXRX_CSR9);
! 786: RAL_WRITE(sc, RT2661_TXRX_CSR9, tmp & ~0x00ffffff);
! 787: }
! 788: break;
! 789:
! 790: case IEEE80211_S_SCAN:
! 791: rt2661_set_chan(sc, ic->ic_bss->ni_chan);
! 792: timeout_add(&sc->scan_to, hz / 5);
! 793: break;
! 794:
! 795: case IEEE80211_S_AUTH:
! 796: case IEEE80211_S_ASSOC:
! 797: rt2661_set_chan(sc, ic->ic_bss->ni_chan);
! 798: break;
! 799:
! 800: case IEEE80211_S_RUN:
! 801: rt2661_set_chan(sc, ic->ic_bss->ni_chan);
! 802:
! 803: ni = ic->ic_bss;
! 804:
! 805: if (ic->ic_opmode != IEEE80211_M_MONITOR) {
! 806: rt2661_set_slottime(sc);
! 807: rt2661_enable_mrr(sc);
! 808: rt2661_set_txpreamble(sc);
! 809: rt2661_set_basicrates(sc);
! 810: rt2661_set_bssid(sc, ni->ni_bssid);
! 811: }
! 812:
! 813: if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
! 814: ic->ic_opmode == IEEE80211_M_IBSS)
! 815: rt2661_prepare_beacon(sc);
! 816:
! 817: if (ic->ic_opmode == IEEE80211_M_STA) {
! 818: /* fake a join to init the tx rate */
! 819: rt2661_newassoc(ic, ni, 1);
! 820: }
! 821:
! 822: if (ic->ic_opmode != IEEE80211_M_MONITOR) {
! 823: sc->ncalls = 0;
! 824: sc->avg_rssi = -95; /* reset EMA */
! 825: timeout_add(&sc->amrr_to, hz / 2);
! 826: rt2661_enable_tsf_sync(sc);
! 827: }
! 828: break;
! 829: }
! 830:
! 831: return (error != 0) ? error : sc->sc_newstate(ic, nstate, arg);
! 832: }
! 833:
! 834: /*
! 835: * Read 16 bits at address 'addr' from the serial EEPROM (either 93C46 or
! 836: * 93C66).
! 837: */
! 838: uint16_t
! 839: rt2661_eeprom_read(struct rt2661_softc *sc, uint8_t addr)
! 840: {
! 841: uint32_t tmp;
! 842: uint16_t val;
! 843: int n;
! 844:
! 845: /* clock C once before the first command */
! 846: RT2661_EEPROM_CTL(sc, 0);
! 847:
! 848: RT2661_EEPROM_CTL(sc, RT2661_S);
! 849: RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_C);
! 850: RT2661_EEPROM_CTL(sc, RT2661_S);
! 851:
! 852: /* write start bit (1) */
! 853: RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_D);
! 854: RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_D | RT2661_C);
! 855:
! 856: /* write READ opcode (10) */
! 857: RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_D);
! 858: RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_D | RT2661_C);
! 859: RT2661_EEPROM_CTL(sc, RT2661_S);
! 860: RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_C);
! 861:
! 862: /* write address (A5-A0 or A7-A0) */
! 863: n = (RAL_READ(sc, RT2661_E2PROM_CSR) & RT2661_93C46) ? 5 : 7;
! 864: for (; n >= 0; n--) {
! 865: RT2661_EEPROM_CTL(sc, RT2661_S |
! 866: (((addr >> n) & 1) << RT2661_SHIFT_D));
! 867: RT2661_EEPROM_CTL(sc, RT2661_S |
! 868: (((addr >> n) & 1) << RT2661_SHIFT_D) | RT2661_C);
! 869: }
! 870:
! 871: RT2661_EEPROM_CTL(sc, RT2661_S);
! 872:
! 873: /* read data Q15-Q0 */
! 874: val = 0;
! 875: for (n = 15; n >= 0; n--) {
! 876: RT2661_EEPROM_CTL(sc, RT2661_S | RT2661_C);
! 877: tmp = RAL_READ(sc, RT2661_E2PROM_CSR);
! 878: val |= ((tmp & RT2661_Q) >> RT2661_SHIFT_Q) << n;
! 879: RT2661_EEPROM_CTL(sc, RT2661_S);
! 880: }
! 881:
! 882: RT2661_EEPROM_CTL(sc, 0);
! 883:
! 884: /* clear Chip Select and clock C */
! 885: RT2661_EEPROM_CTL(sc, RT2661_S);
! 886: RT2661_EEPROM_CTL(sc, 0);
! 887: RT2661_EEPROM_CTL(sc, RT2661_C);
! 888:
! 889: return val;
! 890: }
! 891:
! 892: void
! 893: rt2661_tx_intr(struct rt2661_softc *sc)
! 894: {
! 895: struct ieee80211com *ic = &sc->sc_ic;
! 896: struct ifnet *ifp = &ic->ic_if;
! 897: struct rt2661_tx_ring *txq;
! 898: struct rt2661_tx_data *data;
! 899: struct rt2661_node *rn;
! 900: int qid, retrycnt;
! 901:
! 902: for (;;) {
! 903: const uint32_t val = RAL_READ(sc, RT2661_STA_CSR4);
! 904: if (!(val & RT2661_TX_STAT_VALID))
! 905: break;
! 906:
! 907: /* retrieve the queue in which this frame was sent */
! 908: qid = RT2661_TX_QID(val);
! 909: txq = (qid <= 3) ? &sc->txq[qid] : &sc->mgtq;
! 910:
! 911: /* retrieve rate control algorithm context */
! 912: data = &txq->data[txq->stat];
! 913: rn = (struct rt2661_node *)data->ni;
! 914:
! 915: /* if no frame has been sent, ignore */
! 916: if (rn == NULL)
! 917: continue;
! 918:
! 919: switch (RT2661_TX_RESULT(val)) {
! 920: case RT2661_TX_SUCCESS:
! 921: retrycnt = RT2661_TX_RETRYCNT(val);
! 922:
! 923: DPRINTFN(10, ("data frame sent successfully after "
! 924: "%d retries\n", retrycnt));
! 925: rn->amn.amn_txcnt++;
! 926: if (retrycnt > 0)
! 927: rn->amn.amn_retrycnt++;
! 928: ifp->if_opackets++;
! 929: break;
! 930:
! 931: case RT2661_TX_RETRY_FAIL:
! 932: DPRINTFN(9, ("sending data frame failed (too much "
! 933: "retries)\n"));
! 934: rn->amn.amn_txcnt++;
! 935: rn->amn.amn_retrycnt++;
! 936: ifp->if_oerrors++;
! 937: break;
! 938:
! 939: default:
! 940: /* other failure */
! 941: printf("%s: sending data frame failed 0x%08x\n",
! 942: sc->sc_dev.dv_xname, val);
! 943: ifp->if_oerrors++;
! 944: }
! 945:
! 946: ieee80211_release_node(ic, data->ni);
! 947: data->ni = NULL;
! 948:
! 949: DPRINTFN(15, ("tx done q=%d idx=%u\n", qid, txq->stat));
! 950:
! 951: txq->queued--;
! 952: if (++txq->stat >= txq->count) /* faster than % count */
! 953: txq->stat = 0;
! 954: }
! 955:
! 956: sc->sc_tx_timer = 0;
! 957: ifp->if_flags &= ~IFF_OACTIVE;
! 958: rt2661_start(ifp);
! 959: }
! 960:
! 961: void
! 962: rt2661_tx_dma_intr(struct rt2661_softc *sc, struct rt2661_tx_ring *txq)
! 963: {
! 964: for (;;) {
! 965: struct rt2661_tx_desc *desc = &txq->desc[txq->next];
! 966: struct rt2661_tx_data *data = &txq->data[txq->next];
! 967:
! 968: bus_dmamap_sync(sc->sc_dmat, txq->map,
! 969: txq->next * RT2661_TX_DESC_SIZE, RT2661_TX_DESC_SIZE,
! 970: BUS_DMASYNC_POSTREAD);
! 971:
! 972: if ((letoh32(desc->flags) & RT2661_TX_BUSY) ||
! 973: !(letoh32(desc->flags) & RT2661_TX_VALID))
! 974: break;
! 975:
! 976: bus_dmamap_sync(sc->sc_dmat, data->map, 0,
! 977: data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
! 978: bus_dmamap_unload(sc->sc_dmat, data->map);
! 979: m_freem(data->m);
! 980: data->m = NULL;
! 981: /* node reference is released in rt2661_tx_intr() */
! 982:
! 983: /* descriptor is no longer valid */
! 984: desc->flags &= ~htole32(RT2661_TX_VALID);
! 985:
! 986: bus_dmamap_sync(sc->sc_dmat, txq->map,
! 987: txq->next * RT2661_TX_DESC_SIZE, RT2661_TX_DESC_SIZE,
! 988: BUS_DMASYNC_PREWRITE);
! 989:
! 990: DPRINTFN(15, ("tx dma done q=%p idx=%u\n", txq, txq->next));
! 991:
! 992: if (++txq->next >= txq->count) /* faster than % count */
! 993: txq->next = 0;
! 994: }
! 995: }
! 996:
! 997: void
! 998: rt2661_rx_intr(struct rt2661_softc *sc)
! 999: {
! 1000: struct ieee80211com *ic = &sc->sc_ic;
! 1001: struct ifnet *ifp = &ic->ic_if;
! 1002: struct ieee80211_frame *wh;
! 1003: struct ieee80211_node *ni;
! 1004: struct mbuf *mnew, *m;
! 1005: int error, rssi;
! 1006:
! 1007: for (;;) {
! 1008: struct rt2661_rx_desc *desc = &sc->rxq.desc[sc->rxq.cur];
! 1009: struct rt2661_rx_data *data = &sc->rxq.data[sc->rxq.cur];
! 1010:
! 1011: bus_dmamap_sync(sc->sc_dmat, sc->rxq.map,
! 1012: sc->rxq.cur * RT2661_RX_DESC_SIZE, RT2661_RX_DESC_SIZE,
! 1013: BUS_DMASYNC_POSTREAD);
! 1014:
! 1015: if (letoh32(desc->flags) & RT2661_RX_BUSY)
! 1016: break;
! 1017:
! 1018: if ((letoh32(desc->flags) & RT2661_RX_PHY_ERROR) ||
! 1019: (letoh32(desc->flags) & RT2661_RX_CRC_ERROR)) {
! 1020: /*
! 1021: * This should not happen since we did not request
! 1022: * to receive those frames when we filled TXRX_CSR0.
! 1023: */
! 1024: DPRINTFN(5, ("PHY or CRC error flags 0x%08x\n",
! 1025: letoh32(desc->flags)));
! 1026: ifp->if_ierrors++;
! 1027: goto skip;
! 1028: }
! 1029:
! 1030: if ((letoh32(desc->flags) & RT2661_RX_CIPHER_MASK) != 0) {
! 1031: ifp->if_ierrors++;
! 1032: goto skip;
! 1033: }
! 1034:
! 1035: /*
! 1036: * Try to allocate a new mbuf for this ring element and load it
! 1037: * before processing the current mbuf. If the ring element
! 1038: * cannot be loaded, drop the received packet and reuse the old
! 1039: * mbuf. In the unlikely case that the old mbuf can't be
! 1040: * reloaded either, explicitly panic.
! 1041: */
! 1042: MGETHDR(mnew, M_DONTWAIT, MT_DATA);
! 1043: if (mnew == NULL) {
! 1044: ifp->if_ierrors++;
! 1045: goto skip;
! 1046: }
! 1047: MCLGET(mnew, M_DONTWAIT);
! 1048: if (!(mnew->m_flags & M_EXT)) {
! 1049: m_freem(mnew);
! 1050: ifp->if_ierrors++;
! 1051: goto skip;
! 1052: }
! 1053:
! 1054: bus_dmamap_sync(sc->sc_dmat, data->map, 0,
! 1055: data->map->dm_mapsize, BUS_DMASYNC_POSTREAD);
! 1056: bus_dmamap_unload(sc->sc_dmat, data->map);
! 1057:
! 1058: error = bus_dmamap_load(sc->sc_dmat, data->map,
! 1059: mtod(mnew, void *), MCLBYTES, NULL, BUS_DMA_NOWAIT);
! 1060: if (error != 0) {
! 1061: m_freem(mnew);
! 1062:
! 1063: /* try to reload the old mbuf */
! 1064: error = bus_dmamap_load(sc->sc_dmat, data->map,
! 1065: mtod(data->m, void *), MCLBYTES, NULL,
! 1066: BUS_DMA_NOWAIT);
! 1067: if (error != 0) {
! 1068: /* very unlikely that it will fail... */
! 1069: panic("%s: could not load old rx mbuf",
! 1070: sc->sc_dev.dv_xname);
! 1071: }
! 1072: ifp->if_ierrors++;
! 1073: goto skip;
! 1074: }
! 1075:
! 1076: /*
! 1077: * New mbuf successfully loaded, update Rx ring and continue
! 1078: * processing.
! 1079: */
! 1080: m = data->m;
! 1081: data->m = mnew;
! 1082: desc->physaddr = htole32(data->map->dm_segs->ds_addr);
! 1083:
! 1084: /* finalize mbuf */
! 1085: m->m_pkthdr.rcvif = ifp;
! 1086: m->m_pkthdr.len = m->m_len =
! 1087: (letoh32(desc->flags) >> 16) & 0xfff;
! 1088:
! 1089: #if NBPFILTER > 0
! 1090: if (sc->sc_drvbpf != NULL) {
! 1091: struct mbuf mb;
! 1092: struct rt2661_rx_radiotap_header *tap = &sc->sc_rxtap;
! 1093: uint32_t tsf_lo, tsf_hi;
! 1094:
! 1095: /* get timestamp (low and high 32 bits) */
! 1096: tsf_hi = RAL_READ(sc, RT2661_TXRX_CSR13);
! 1097: tsf_lo = RAL_READ(sc, RT2661_TXRX_CSR12);
! 1098:
! 1099: tap->wr_tsf =
! 1100: htole64(((uint64_t)tsf_hi << 32) | tsf_lo);
! 1101: tap->wr_flags = 0;
! 1102: tap->wr_rate = rt2661_rxrate(desc);
! 1103: tap->wr_chan_freq = htole16(sc->sc_curchan->ic_freq);
! 1104: tap->wr_chan_flags = htole16(sc->sc_curchan->ic_flags);
! 1105: tap->wr_antsignal = desc->rssi;
! 1106:
! 1107: mb.m_data = (caddr_t)tap;
! 1108: mb.m_len = sc->sc_rxtap_len;
! 1109: mb.m_next = m;
! 1110: mb.m_nextpkt = NULL;
! 1111: mb.m_type = 0;
! 1112: mb.m_flags = 0;
! 1113: bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN);
! 1114: }
! 1115: #endif
! 1116:
! 1117: wh = mtod(m, struct ieee80211_frame *);
! 1118: ni = ieee80211_find_rxnode(ic, wh);
! 1119:
! 1120: /* send the frame to the 802.11 layer */
! 1121: ieee80211_input(ifp, m, ni, desc->rssi, 0);
! 1122:
! 1123: /*-
! 1124: * Keep track of the average RSSI using an Exponential Moving
! 1125: * Average (EMA) of 8 Wilder's days:
! 1126: * avg = (1 / N) x rssi + ((N - 1) / N) x avg
! 1127: */
! 1128: rssi = rt2661_get_rssi(sc, desc->rssi);
! 1129: sc->avg_rssi = (rssi + 7 * sc->avg_rssi) / 8;
! 1130:
! 1131: /* node is no longer needed */
! 1132: ieee80211_release_node(ic, ni);
! 1133:
! 1134: skip: desc->flags |= htole32(RT2661_RX_BUSY);
! 1135:
! 1136: bus_dmamap_sync(sc->sc_dmat, sc->rxq.map,
! 1137: sc->rxq.cur * RT2661_RX_DESC_SIZE, RT2661_RX_DESC_SIZE,
! 1138: BUS_DMASYNC_PREWRITE);
! 1139:
! 1140: DPRINTFN(15, ("rx intr idx=%u\n", sc->rxq.cur));
! 1141:
! 1142: sc->rxq.cur = (sc->rxq.cur + 1) % RT2661_RX_RING_COUNT;
! 1143: }
! 1144:
! 1145: /*
! 1146: * In HostAP mode, ieee80211_input() will enqueue packets in if_snd
! 1147: * without calling if_start().
! 1148: */
! 1149: if (!IFQ_IS_EMPTY(&ifp->if_snd) && !(ifp->if_flags & IFF_OACTIVE))
! 1150: rt2661_start(ifp);
! 1151: }
! 1152:
! 1153: /*
! 1154: * This function is called in HostAP or IBSS modes when it's time to send a
! 1155: * new beacon (every ni_intval milliseconds).
! 1156: */
! 1157: void
! 1158: rt2661_mcu_beacon_expire(struct rt2661_softc *sc)
! 1159: {
! 1160: struct ieee80211com *ic = &sc->sc_ic;
! 1161:
! 1162: if (sc->sc_flags & RT2661_UPDATE_SLOT) {
! 1163: sc->sc_flags &= ~RT2661_UPDATE_SLOT;
! 1164: sc->sc_flags |= RT2661_SET_SLOTTIME;
! 1165: } else if (sc->sc_flags & RT2661_SET_SLOTTIME) {
! 1166: sc->sc_flags &= ~RT2661_SET_SLOTTIME;
! 1167: rt2661_set_slottime(sc);
! 1168: }
! 1169:
! 1170: if (ic->ic_curmode == IEEE80211_MODE_11G) {
! 1171: /* update ERP Information Element */
! 1172: RAL_WRITE_1(sc, sc->erp_csr, ic->ic_bss->ni_erp);
! 1173: RAL_RW_BARRIER_1(sc, sc->erp_csr);
! 1174: }
! 1175:
! 1176: DPRINTFN(15, ("beacon expired\n"));
! 1177: }
! 1178:
! 1179: void
! 1180: rt2661_mcu_wakeup(struct rt2661_softc *sc)
! 1181: {
! 1182: RAL_WRITE(sc, RT2661_MAC_CSR11, 5 << 16);
! 1183:
! 1184: RAL_WRITE(sc, RT2661_SOFT_RESET_CSR, 0x7);
! 1185: RAL_WRITE(sc, RT2661_IO_CNTL_CSR, 0x18);
! 1186: RAL_WRITE(sc, RT2661_PCI_USEC_CSR, 0x20);
! 1187:
! 1188: /* send wakeup command to MCU */
! 1189: rt2661_tx_cmd(sc, RT2661_MCU_CMD_WAKEUP, 0);
! 1190: }
! 1191:
! 1192: void
! 1193: rt2661_mcu_cmd_intr(struct rt2661_softc *sc)
! 1194: {
! 1195: RAL_READ(sc, RT2661_M2H_CMD_DONE_CSR);
! 1196: RAL_WRITE(sc, RT2661_M2H_CMD_DONE_CSR, 0xffffffff);
! 1197: }
! 1198:
! 1199: int
! 1200: rt2661_intr(void *arg)
! 1201: {
! 1202: struct rt2661_softc *sc = arg;
! 1203: struct ifnet *ifp = &sc->sc_ic.ic_if;
! 1204: uint32_t r1, r2;
! 1205:
! 1206: r1 = RAL_READ(sc, RT2661_INT_SOURCE_CSR);
! 1207: r2 = RAL_READ(sc, RT2661_MCU_INT_SOURCE_CSR);
! 1208: if (r1 == 0 && r2 == 0)
! 1209: return 0; /* not for us */
! 1210:
! 1211: /* disable MAC and MCU interrupts */
! 1212: RAL_WRITE(sc, RT2661_INT_MASK_CSR, 0xffffff7f);
! 1213: RAL_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0xffffffff);
! 1214:
! 1215: /* acknowledge interrupts */
! 1216: RAL_WRITE(sc, RT2661_INT_SOURCE_CSR, r1);
! 1217: RAL_WRITE(sc, RT2661_MCU_INT_SOURCE_CSR, r2);
! 1218:
! 1219: /* don't re-enable interrupts if we're shutting down */
! 1220: if (!(ifp->if_flags & IFF_RUNNING))
! 1221: return 0;
! 1222:
! 1223: if (r1 & RT2661_MGT_DONE)
! 1224: rt2661_tx_dma_intr(sc, &sc->mgtq);
! 1225:
! 1226: if (r1 & RT2661_RX_DONE)
! 1227: rt2661_rx_intr(sc);
! 1228:
! 1229: if (r1 & RT2661_TX0_DMA_DONE)
! 1230: rt2661_tx_dma_intr(sc, &sc->txq[0]);
! 1231:
! 1232: if (r1 & RT2661_TX1_DMA_DONE)
! 1233: rt2661_tx_dma_intr(sc, &sc->txq[1]);
! 1234:
! 1235: if (r1 & RT2661_TX2_DMA_DONE)
! 1236: rt2661_tx_dma_intr(sc, &sc->txq[2]);
! 1237:
! 1238: if (r1 & RT2661_TX3_DMA_DONE)
! 1239: rt2661_tx_dma_intr(sc, &sc->txq[3]);
! 1240:
! 1241: if (r1 & RT2661_TX_DONE)
! 1242: rt2661_tx_intr(sc);
! 1243:
! 1244: if (r2 & RT2661_MCU_CMD_DONE)
! 1245: rt2661_mcu_cmd_intr(sc);
! 1246:
! 1247: if (r2 & RT2661_MCU_BEACON_EXPIRE)
! 1248: rt2661_mcu_beacon_expire(sc);
! 1249:
! 1250: if (r2 & RT2661_MCU_WAKEUP)
! 1251: rt2661_mcu_wakeup(sc);
! 1252:
! 1253: /* re-enable MAC and MCU interrupts */
! 1254: RAL_WRITE(sc, RT2661_INT_MASK_CSR, 0x0000ff10);
! 1255: RAL_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0);
! 1256:
! 1257: return 1;
! 1258: }
! 1259:
! 1260: /* quickly determine if a given rate is CCK or OFDM */
! 1261: #define RAL_RATE_IS_OFDM(rate) ((rate) >= 12 && (rate) != 22)
! 1262:
! 1263: #define RAL_ACK_SIZE 14 /* 10 + 4(FCS) */
! 1264: #define RAL_CTS_SIZE 14 /* 10 + 4(FCS) */
! 1265:
! 1266: /*
! 1267: * This function is only used by the Rx radiotap code. It returns the rate at
! 1268: * which a given frame was received.
! 1269: */
! 1270: #if NBPFILTER > 0
! 1271: uint8_t
! 1272: rt2661_rxrate(const struct rt2661_rx_desc *desc)
! 1273: {
! 1274: if (letoh32(desc->flags) & RT2661_RX_OFDM) {
! 1275: /* reverse function of rt2661_plcp_signal */
! 1276: switch (desc->rate & 0xf) {
! 1277: case 0xb: return 12;
! 1278: case 0xf: return 18;
! 1279: case 0xa: return 24;
! 1280: case 0xe: return 36;
! 1281: case 0x9: return 48;
! 1282: case 0xd: return 72;
! 1283: case 0x8: return 96;
! 1284: case 0xc: return 108;
! 1285: }
! 1286: } else {
! 1287: if (desc->rate == 10)
! 1288: return 2;
! 1289: if (desc->rate == 20)
! 1290: return 4;
! 1291: if (desc->rate == 55)
! 1292: return 11;
! 1293: if (desc->rate == 110)
! 1294: return 22;
! 1295: }
! 1296: return 2; /* should not get there */
! 1297: }
! 1298: #endif
! 1299:
! 1300: /*
! 1301: * Return the expected ack rate for a frame transmitted at rate `rate'.
! 1302: */
! 1303: int
! 1304: rt2661_ack_rate(struct ieee80211com *ic, int rate)
! 1305: {
! 1306: switch (rate) {
! 1307: /* CCK rates */
! 1308: case 2:
! 1309: return 2;
! 1310: case 4:
! 1311: case 11:
! 1312: case 22:
! 1313: return (ic->ic_curmode == IEEE80211_MODE_11B) ? 4 : rate;
! 1314:
! 1315: /* OFDM rates */
! 1316: case 12:
! 1317: case 18:
! 1318: return 12;
! 1319: case 24:
! 1320: case 36:
! 1321: return 24;
! 1322: case 48:
! 1323: case 72:
! 1324: case 96:
! 1325: case 108:
! 1326: return 48;
! 1327: }
! 1328:
! 1329: /* default to 1Mbps */
! 1330: return 2;
! 1331: }
! 1332:
! 1333: /*
! 1334: * Compute the duration (in us) needed to transmit `len' bytes at rate `rate'.
! 1335: * The function automatically determines the operating mode depending on the
! 1336: * given rate. `flags' indicates whether short preamble is in use or not.
! 1337: */
! 1338: uint16_t
! 1339: rt2661_txtime(int len, int rate, uint32_t flags)
! 1340: {
! 1341: uint16_t txtime;
! 1342:
! 1343: if (RAL_RATE_IS_OFDM(rate)) {
! 1344: /* IEEE Std 802.11g-2003, pp. 44 */
! 1345: txtime = (8 + 4 * len + 3 + rate - 1) / rate;
! 1346: txtime = 16 + 4 + 4 * txtime + 6;
! 1347: } else {
! 1348: /* IEEE Std 802.11b-1999, pp. 28 */
! 1349: txtime = (16 * len + rate - 1) / rate;
! 1350: if (rate != 2 && (flags & IEEE80211_F_SHPREAMBLE))
! 1351: txtime += 72 + 24;
! 1352: else
! 1353: txtime += 144 + 48;
! 1354: }
! 1355: return txtime;
! 1356: }
! 1357:
! 1358: uint8_t
! 1359: rt2661_plcp_signal(int rate)
! 1360: {
! 1361: switch (rate) {
! 1362: /* CCK rates (returned values are device-dependent) */
! 1363: case 2: return 0x0;
! 1364: case 4: return 0x1;
! 1365: case 11: return 0x2;
! 1366: case 22: return 0x3;
! 1367:
! 1368: /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
! 1369: case 12: return 0xb;
! 1370: case 18: return 0xf;
! 1371: case 24: return 0xa;
! 1372: case 36: return 0xe;
! 1373: case 48: return 0x9;
! 1374: case 72: return 0xd;
! 1375: case 96: return 0x8;
! 1376: case 108: return 0xc;
! 1377:
! 1378: /* unsupported rates (should not get there) */
! 1379: default: return 0xff;
! 1380: }
! 1381: }
! 1382:
! 1383: void
! 1384: rt2661_setup_tx_desc(struct rt2661_softc *sc, struct rt2661_tx_desc *desc,
! 1385: uint32_t flags, uint16_t xflags, int len, int rate,
! 1386: const bus_dma_segment_t *segs, int nsegs, int ac)
! 1387: {
! 1388: struct ieee80211com *ic = &sc->sc_ic;
! 1389: uint16_t plcp_length;
! 1390: int i, remainder;
! 1391:
! 1392: desc->flags = htole32(flags);
! 1393: desc->flags |= htole32(len << 16);
! 1394: desc->flags |= htole32(RT2661_TX_BUSY | RT2661_TX_VALID);
! 1395:
! 1396: desc->xflags = htole16(xflags);
! 1397: desc->xflags |= htole16(nsegs << 13);
! 1398:
! 1399: desc->wme = htole16(
! 1400: RT2661_QID(ac) |
! 1401: RT2661_AIFSN(2) |
! 1402: RT2661_LOGCWMIN(4) |
! 1403: RT2661_LOGCWMAX(10));
! 1404:
! 1405: /*
! 1406: * Remember in which queue this frame was sent. This field is driver
! 1407: * private data only. It will be made available by the NIC in STA_CSR4
! 1408: * on Tx interrupts.
! 1409: */
! 1410: desc->qid = ac;
! 1411:
! 1412: /* setup PLCP fields */
! 1413: desc->plcp_signal = rt2661_plcp_signal(rate);
! 1414: desc->plcp_service = 4;
! 1415:
! 1416: len += IEEE80211_CRC_LEN;
! 1417: if (RAL_RATE_IS_OFDM(rate)) {
! 1418: desc->flags |= htole32(RT2661_TX_OFDM);
! 1419:
! 1420: plcp_length = len & 0xfff;
! 1421: desc->plcp_length_hi = plcp_length >> 6;
! 1422: desc->plcp_length_lo = plcp_length & 0x3f;
! 1423: } else {
! 1424: plcp_length = (16 * len + rate - 1) / rate;
! 1425: if (rate == 22) {
! 1426: remainder = (16 * len) % 22;
! 1427: if (remainder != 0 && remainder < 7)
! 1428: desc->plcp_service |= RT2661_PLCP_LENGEXT;
! 1429: }
! 1430: desc->plcp_length_hi = plcp_length >> 8;
! 1431: desc->plcp_length_lo = plcp_length & 0xff;
! 1432:
! 1433: if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
! 1434: desc->plcp_signal |= 0x08;
! 1435: }
! 1436:
! 1437: /* RT2x61 supports scatter with up to 5 segments */
! 1438: for (i = 0; i < nsegs; i++) {
! 1439: desc->addr[i] = htole32(segs[i].ds_addr);
! 1440: desc->len [i] = htole16(segs[i].ds_len);
! 1441: }
! 1442: }
! 1443:
! 1444: int
! 1445: rt2661_tx_mgt(struct rt2661_softc *sc, struct mbuf *m0,
! 1446: struct ieee80211_node *ni)
! 1447: {
! 1448: struct ieee80211com *ic = &sc->sc_ic;
! 1449: struct ifnet *ifp = &ic->ic_if;
! 1450: struct rt2661_tx_desc *desc;
! 1451: struct rt2661_tx_data *data;
! 1452: struct ieee80211_frame *wh;
! 1453: uint16_t dur;
! 1454: uint32_t flags = 0;
! 1455: int rate, error;
! 1456:
! 1457: desc = &sc->mgtq.desc[sc->mgtq.cur];
! 1458: data = &sc->mgtq.data[sc->mgtq.cur];
! 1459:
! 1460: /* send mgt frames at the lowest available rate */
! 1461: rate = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ? 12 : 2;
! 1462:
! 1463: wh = mtod(m0, struct ieee80211_frame *);
! 1464:
! 1465: if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
! 1466: m0 = ieee80211_wep_crypt(ifp, m0, 1);
! 1467: if (m0 == NULL)
! 1468: return ENOBUFS;
! 1469:
! 1470: /* packet header may have moved, reset our local pointer */
! 1471: wh = mtod(m0, struct ieee80211_frame *);
! 1472: }
! 1473:
! 1474: error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
! 1475: BUS_DMA_NOWAIT);
! 1476: if (error != 0) {
! 1477: printf("%s: could not map mbuf (error %d)\n",
! 1478: sc->sc_dev.dv_xname, error);
! 1479: m_freem(m0);
! 1480: return error;
! 1481: }
! 1482:
! 1483: #if NBPFILTER > 0
! 1484: if (sc->sc_drvbpf != NULL) {
! 1485: struct mbuf mb;
! 1486: struct rt2661_tx_radiotap_header *tap = &sc->sc_txtap;
! 1487:
! 1488: tap->wt_flags = 0;
! 1489: tap->wt_rate = rate;
! 1490: tap->wt_chan_freq = htole16(sc->sc_curchan->ic_freq);
! 1491: tap->wt_chan_flags = htole16(sc->sc_curchan->ic_flags);
! 1492:
! 1493: mb.m_data = (caddr_t)tap;
! 1494: mb.m_len = sc->sc_txtap_len;
! 1495: mb.m_next = m0;
! 1496: mb.m_nextpkt = NULL;
! 1497: mb.m_type = 0;
! 1498: mb.m_flags = 0;
! 1499: bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
! 1500: }
! 1501: #endif
! 1502:
! 1503: data->m = m0;
! 1504: data->ni = ni;
! 1505:
! 1506: if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
! 1507: flags |= RT2661_TX_NEED_ACK;
! 1508:
! 1509: dur = rt2661_txtime(RAL_ACK_SIZE, rate, ic->ic_flags) +
! 1510: sc->sifs;
! 1511: *(uint16_t *)wh->i_dur = htole16(dur);
! 1512:
! 1513: /* tell hardware to set timestamp in probe responses */
! 1514: if ((wh->i_fc[0] &
! 1515: (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==
! 1516: (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP))
! 1517: flags |= RT2661_TX_TIMESTAMP;
! 1518: }
! 1519:
! 1520: rt2661_setup_tx_desc(sc, desc, flags, 0 /* XXX HWSEQ */,
! 1521: m0->m_pkthdr.len, rate, data->map->dm_segs, data->map->dm_nsegs,
! 1522: RT2661_QID_MGT);
! 1523:
! 1524: bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
! 1525: BUS_DMASYNC_PREWRITE);
! 1526: bus_dmamap_sync(sc->sc_dmat, sc->mgtq.map,
! 1527: sc->mgtq.cur * RT2661_TX_DESC_SIZE, RT2661_TX_DESC_SIZE,
! 1528: BUS_DMASYNC_PREWRITE);
! 1529:
! 1530: DPRINTFN(10, ("sending mgt frame len=%u idx=%u rate=%u\n",
! 1531: m0->m_pkthdr.len, sc->mgtq.cur, rate));
! 1532:
! 1533: /* kick mgt */
! 1534: sc->mgtq.queued++;
! 1535: sc->mgtq.cur = (sc->mgtq.cur + 1) % RT2661_MGT_RING_COUNT;
! 1536: RAL_WRITE(sc, RT2661_TX_CNTL_CSR, RT2661_KICK_MGT);
! 1537:
! 1538: return 0;
! 1539: }
! 1540:
! 1541: int
! 1542: rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m0,
! 1543: struct ieee80211_node *ni, int ac)
! 1544: {
! 1545: struct ieee80211com *ic = &sc->sc_ic;
! 1546: struct ifnet *ifp = &ic->ic_if;
! 1547: struct rt2661_tx_ring *txq = &sc->txq[ac];
! 1548: struct rt2661_tx_desc *desc;
! 1549: struct rt2661_tx_data *data;
! 1550: struct ieee80211_frame *wh;
! 1551: struct mbuf *mnew;
! 1552: uint16_t dur;
! 1553: uint32_t flags = 0;
! 1554: int pktlen, rate, needcts = 0, needrts = 0, error;
! 1555:
! 1556: wh = mtod(m0, struct ieee80211_frame *);
! 1557:
! 1558: if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
! 1559: m0 = ieee80211_wep_crypt(ifp, m0, 1);
! 1560: if (m0 == NULL)
! 1561: return ENOBUFS;
! 1562:
! 1563: /* packet header may have moved, reset our local pointer */
! 1564: wh = mtod(m0, struct ieee80211_frame *);
! 1565: }
! 1566:
! 1567: /* compute actual packet length (including CRC and crypto overhead) */
! 1568: pktlen = m0->m_pkthdr.len + IEEE80211_CRC_LEN;
! 1569:
! 1570: /* pickup a rate */
! 1571: if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
! 1572: /* multicast frames are sent at the lowest avail. rate */
! 1573: rate = ni->ni_rates.rs_rates[0];
! 1574: } else if (ic->ic_fixed_rate != -1) {
! 1575: rate = ic->ic_sup_rates[ic->ic_curmode].
! 1576: rs_rates[ic->ic_fixed_rate];
! 1577: } else
! 1578: rate = ni->ni_rates.rs_rates[ni->ni_txrate];
! 1579: if (rate == 0)
! 1580: rate = 2; /* XXX should not happen */
! 1581: rate &= IEEE80211_RATE_VAL;
! 1582:
! 1583: /*
! 1584: * Packet Bursting: backoff after ppb=8 frames to give other STAs a
! 1585: * chance to contend for the wireless medium.
! 1586: */
! 1587: if (ic->ic_opmode == IEEE80211_M_STA && (ni->ni_txseq & 7))
! 1588: flags |= RT2661_TX_IFS_SIFS;
! 1589:
! 1590: /* check if RTS/CTS or CTS-to-self protection must be used */
! 1591: if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
! 1592: /* multicast frames are not sent at OFDM rates in 802.11b/g */
! 1593: if (pktlen > ic->ic_rtsthreshold) {
! 1594: needrts = 1; /* RTS/CTS based on frame length */
! 1595: } else if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
! 1596: RAL_RATE_IS_OFDM(rate)) {
! 1597: if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
! 1598: needcts = 1; /* CTS-to-self */
! 1599: else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
! 1600: needrts = 1; /* RTS/CTS */
! 1601: }
! 1602: }
! 1603: if (needrts || needcts) {
! 1604: struct mbuf *mprot;
! 1605: int protrate, ackrate;
! 1606: uint16_t dur;
! 1607:
! 1608: protrate = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ? 12 : 2;
! 1609: ackrate = rt2661_ack_rate(ic, rate);
! 1610:
! 1611: dur = rt2661_txtime(pktlen, rate, ic->ic_flags) +
! 1612: rt2661_txtime(RAL_ACK_SIZE, ackrate, ic->ic_flags) +
! 1613: 2 * sc->sifs;
! 1614: if (needrts) {
! 1615: dur += rt2661_txtime(RAL_CTS_SIZE, rt2661_ack_rate(ic,
! 1616: protrate), ic->ic_flags) + sc->sifs;
! 1617: mprot = ieee80211_get_rts(ic, wh, dur);
! 1618: } else {
! 1619: mprot = ieee80211_get_cts_to_self(ic, dur);
! 1620: }
! 1621: if (mprot == NULL) {
! 1622: printf("%s: could not allocate protection frame\n",
! 1623: sc->sc_dev.dv_xname);
! 1624: m_freem(m0);
! 1625: return ENOBUFS;
! 1626: }
! 1627:
! 1628: desc = &txq->desc[txq->cur];
! 1629: data = &txq->data[txq->cur];
! 1630:
! 1631: error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, mprot,
! 1632: BUS_DMA_NOWAIT);
! 1633: if (error != 0) {
! 1634: printf("%s: could not map mbuf (error %d)\n",
! 1635: sc->sc_dev.dv_xname, error);
! 1636: m_freem(mprot);
! 1637: m_freem(m0);
! 1638: return error;
! 1639: }
! 1640:
! 1641: data->m = mprot;
! 1642: /* avoid multiple free() of the same node for each fragment */
! 1643: data->ni = ieee80211_ref_node(ni);
! 1644:
! 1645: /* XXX may want to pass the protection frame to BPF */
! 1646:
! 1647: rt2661_setup_tx_desc(sc, desc,
! 1648: (needrts ? RT2661_TX_NEED_ACK : 0) | RT2661_TX_MORE_FRAG,
! 1649: 0, mprot->m_pkthdr.len, protrate, data->map->dm_segs,
! 1650: data->map->dm_nsegs, ac);
! 1651:
! 1652: bus_dmamap_sync(sc->sc_dmat, data->map, 0,
! 1653: data->map->dm_mapsize, BUS_DMASYNC_PREWRITE);
! 1654: bus_dmamap_sync(sc->sc_dmat, txq->map,
! 1655: txq->cur * RT2661_TX_DESC_SIZE, RT2661_TX_DESC_SIZE,
! 1656: BUS_DMASYNC_PREWRITE);
! 1657:
! 1658: txq->queued++;
! 1659: txq->cur = (txq->cur + 1) % RT2661_TX_RING_COUNT;
! 1660:
! 1661: flags |= RT2661_TX_LONG_RETRY | RT2661_TX_IFS_SIFS;
! 1662: }
! 1663:
! 1664: data = &txq->data[txq->cur];
! 1665: desc = &txq->desc[txq->cur];
! 1666:
! 1667: error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
! 1668: BUS_DMA_NOWAIT);
! 1669: if (error != 0 && error != EFBIG) {
! 1670: printf("%s: could not map mbuf (error %d)\n",
! 1671: sc->sc_dev.dv_xname, error);
! 1672: m_freem(m0);
! 1673: return error;
! 1674: }
! 1675: if (error != 0) {
! 1676: /* too many fragments, linearize */
! 1677:
! 1678: MGETHDR(mnew, M_DONTWAIT, MT_DATA);
! 1679: if (mnew == NULL) {
! 1680: m_freem(m0);
! 1681: return ENOMEM;
! 1682: }
! 1683: M_DUP_PKTHDR(mnew, m0);
! 1684: if (m0->m_pkthdr.len > MHLEN) {
! 1685: MCLGET(mnew, M_DONTWAIT);
! 1686: if (!(mnew->m_flags & M_EXT)) {
! 1687: m_freem(m0);
! 1688: m_freem(mnew);
! 1689: return ENOMEM;
! 1690: }
! 1691: }
! 1692:
! 1693: m_copydata(m0, 0, m0->m_pkthdr.len, mtod(mnew, caddr_t));
! 1694: m_freem(m0);
! 1695: mnew->m_len = mnew->m_pkthdr.len;
! 1696: m0 = mnew;
! 1697:
! 1698: error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
! 1699: BUS_DMA_NOWAIT);
! 1700: if (error != 0) {
! 1701: printf("%s: could not map mbuf (error %d)\n",
! 1702: sc->sc_dev.dv_xname, error);
! 1703: m_freem(m0);
! 1704: return error;
! 1705: }
! 1706:
! 1707: /* packet header have moved, reset our local pointer */
! 1708: wh = mtod(m0, struct ieee80211_frame *);
! 1709: }
! 1710:
! 1711: #if NBPFILTER > 0
! 1712: if (sc->sc_drvbpf != NULL) {
! 1713: struct mbuf mb;
! 1714: struct rt2661_tx_radiotap_header *tap = &sc->sc_txtap;
! 1715:
! 1716: tap->wt_flags = 0;
! 1717: tap->wt_rate = rate;
! 1718: tap->wt_chan_freq = htole16(sc->sc_curchan->ic_freq);
! 1719: tap->wt_chan_flags = htole16(sc->sc_curchan->ic_flags);
! 1720:
! 1721: mb.m_data = (caddr_t)tap;
! 1722: mb.m_len = sc->sc_txtap_len;
! 1723: mb.m_next = m0;
! 1724: mb.m_nextpkt = NULL;
! 1725: mb.m_type = 0;
! 1726: mb.m_flags = 0;
! 1727: bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
! 1728: }
! 1729: #endif
! 1730:
! 1731: data->m = m0;
! 1732: data->ni = ni;
! 1733:
! 1734: if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
! 1735: flags |= RT2661_TX_NEED_ACK;
! 1736:
! 1737: dur = rt2661_txtime(RAL_ACK_SIZE, rt2661_ack_rate(ic, rate),
! 1738: ic->ic_flags) + sc->sifs;
! 1739: *(uint16_t *)wh->i_dur = htole16(dur);
! 1740: }
! 1741:
! 1742: rt2661_setup_tx_desc(sc, desc, flags, 0, m0->m_pkthdr.len, rate,
! 1743: data->map->dm_segs, data->map->dm_nsegs, ac);
! 1744:
! 1745: bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
! 1746: BUS_DMASYNC_PREWRITE);
! 1747: bus_dmamap_sync(sc->sc_dmat, txq->map, txq->cur * RT2661_TX_DESC_SIZE,
! 1748: RT2661_TX_DESC_SIZE, BUS_DMASYNC_PREWRITE);
! 1749:
! 1750: DPRINTFN(10, ("sending data frame len=%u idx=%u rate=%u\n",
! 1751: m0->m_pkthdr.len, txq->cur, rate));
! 1752:
! 1753: /* kick Tx */
! 1754: txq->queued++;
! 1755: txq->cur = (txq->cur + 1) % RT2661_TX_RING_COUNT;
! 1756: RAL_WRITE(sc, RT2661_TX_CNTL_CSR, 1);
! 1757:
! 1758: return 0;
! 1759: }
! 1760:
! 1761: void
! 1762: rt2661_start(struct ifnet *ifp)
! 1763: {
! 1764: struct rt2661_softc *sc = ifp->if_softc;
! 1765: struct ieee80211com *ic = &sc->sc_ic;
! 1766: struct mbuf *m0;
! 1767: struct ieee80211_node *ni;
! 1768:
! 1769: /*
! 1770: * net80211 may still try to send management frames even if the
! 1771: * IFF_RUNNING flag is not set...
! 1772: */
! 1773: if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
! 1774: return;
! 1775:
! 1776: for (;;) {
! 1777: IF_POLL(&ic->ic_mgtq, m0);
! 1778: if (m0 != NULL) {
! 1779: if (sc->mgtq.queued >= RT2661_MGT_RING_COUNT) {
! 1780: ifp->if_flags |= IFF_OACTIVE;
! 1781: break;
! 1782: }
! 1783: IF_DEQUEUE(&ic->ic_mgtq, m0);
! 1784:
! 1785: ni = (struct ieee80211_node *)m0->m_pkthdr.rcvif;
! 1786: m0->m_pkthdr.rcvif = NULL;
! 1787: #if NBPFILTER > 0
! 1788: if (ic->ic_rawbpf != NULL)
! 1789: bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT);
! 1790: #endif
! 1791: if (rt2661_tx_mgt(sc, m0, ni) != 0)
! 1792: break;
! 1793:
! 1794: } else {
! 1795: if (ic->ic_state != IEEE80211_S_RUN)
! 1796: break;
! 1797: IFQ_POLL(&ifp->if_snd, m0);
! 1798: if (m0 == NULL)
! 1799: break;
! 1800: if (sc->txq[0].queued >= RT2661_TX_RING_COUNT - 1) {
! 1801: /* there is no place left in this ring */
! 1802: ifp->if_flags |= IFF_OACTIVE;
! 1803: break;
! 1804: }
! 1805: IFQ_DEQUEUE(&ifp->if_snd, m0);
! 1806: #if NBPFILTER > 0
! 1807: if (ifp->if_bpf != NULL)
! 1808: bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
! 1809: #endif
! 1810: m0 = ieee80211_encap(ifp, m0, &ni);
! 1811: if (m0 == NULL)
! 1812: continue;
! 1813: #if NBPFILTER > 0
! 1814: if (ic->ic_rawbpf != NULL)
! 1815: bpf_mtap(ic->ic_rawbpf, m0,
! 1816: BPF_DIRECTION_OUT);
! 1817: #endif
! 1818: if (rt2661_tx_data(sc, m0, ni, 0) != 0) {
! 1819: if (ni != NULL)
! 1820: ieee80211_release_node(ic, ni);
! 1821: ifp->if_oerrors++;
! 1822: break;
! 1823: }
! 1824: }
! 1825:
! 1826: sc->sc_tx_timer = 5;
! 1827: ifp->if_timer = 1;
! 1828: }
! 1829: }
! 1830:
! 1831: void
! 1832: rt2661_watchdog(struct ifnet *ifp)
! 1833: {
! 1834: struct rt2661_softc *sc = ifp->if_softc;
! 1835:
! 1836: ifp->if_timer = 0;
! 1837:
! 1838: if (sc->sc_tx_timer > 0) {
! 1839: if (--sc->sc_tx_timer == 0) {
! 1840: printf("%s: device timeout\n", sc->sc_dev.dv_xname);
! 1841: rt2661_init(ifp);
! 1842: ifp->if_oerrors++;
! 1843: return;
! 1844: }
! 1845: ifp->if_timer = 1;
! 1846: }
! 1847:
! 1848: ieee80211_watchdog(ifp);
! 1849: }
! 1850:
! 1851: int
! 1852: rt2661_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
! 1853: {
! 1854: struct rt2661_softc *sc = ifp->if_softc;
! 1855: struct ieee80211com *ic = &sc->sc_ic;
! 1856: struct ifaddr *ifa;
! 1857: struct ifreq *ifr;
! 1858: int s, error = 0;
! 1859:
! 1860: s = splnet();
! 1861:
! 1862: switch (cmd) {
! 1863: case SIOCSIFADDR:
! 1864: ifa = (struct ifaddr *)data;
! 1865: ifp->if_flags |= IFF_UP;
! 1866: #ifdef INET
! 1867: if (ifa->ifa_addr->sa_family == AF_INET)
! 1868: arp_ifinit(&ic->ic_ac, ifa);
! 1869: #endif
! 1870: /* FALLTHROUGH */
! 1871: case SIOCSIFFLAGS:
! 1872: if (ifp->if_flags & IFF_UP) {
! 1873: if (ifp->if_flags & IFF_RUNNING)
! 1874: rt2661_update_promisc(sc);
! 1875: else
! 1876: rt2661_init(ifp);
! 1877: } else {
! 1878: if (ifp->if_flags & IFF_RUNNING)
! 1879: rt2661_stop(ifp, 1);
! 1880: }
! 1881: break;
! 1882:
! 1883: case SIOCADDMULTI:
! 1884: case SIOCDELMULTI:
! 1885: ifr = (struct ifreq *)data;
! 1886: error = (cmd == SIOCADDMULTI) ?
! 1887: ether_addmulti(ifr, &ic->ic_ac) :
! 1888: ether_delmulti(ifr, &ic->ic_ac);
! 1889:
! 1890: if (error == ENETRESET)
! 1891: error = 0;
! 1892: break;
! 1893:
! 1894: case SIOCS80211CHANNEL:
! 1895: /*
! 1896: * This allows for fast channel switching in monitor mode
! 1897: * (used by kismet). In IBSS mode, we must explicitly reset
! 1898: * the interface to generate a new beacon frame.
! 1899: */
! 1900: error = ieee80211_ioctl(ifp, cmd, data);
! 1901: if (error == ENETRESET &&
! 1902: ic->ic_opmode == IEEE80211_M_MONITOR) {
! 1903: if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
! 1904: (IFF_UP | IFF_RUNNING))
! 1905: rt2661_set_chan(sc, ic->ic_ibss_chan);
! 1906: error = 0;
! 1907: }
! 1908: break;
! 1909:
! 1910: default:
! 1911: error = ieee80211_ioctl(ifp, cmd, data);
! 1912: }
! 1913:
! 1914: if (error == ENETRESET) {
! 1915: if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
! 1916: (IFF_UP | IFF_RUNNING))
! 1917: rt2661_init(ifp);
! 1918: error = 0;
! 1919: }
! 1920:
! 1921: splx(s);
! 1922:
! 1923: return error;
! 1924: }
! 1925:
! 1926: void
! 1927: rt2661_bbp_write(struct rt2661_softc *sc, uint8_t reg, uint8_t val)
! 1928: {
! 1929: uint32_t tmp;
! 1930: int ntries;
! 1931:
! 1932: for (ntries = 0; ntries < 100; ntries++) {
! 1933: if (!(RAL_READ(sc, RT2661_PHY_CSR3) & RT2661_BBP_BUSY))
! 1934: break;
! 1935: DELAY(1);
! 1936: }
! 1937: if (ntries == 100) {
! 1938: printf("%s: could not write to BBP\n", sc->sc_dev.dv_xname);
! 1939: return;
! 1940: }
! 1941:
! 1942: tmp = RT2661_BBP_BUSY | (reg & 0x7f) << 8 | val;
! 1943: RAL_WRITE(sc, RT2661_PHY_CSR3, tmp);
! 1944:
! 1945: DPRINTFN(15, ("BBP R%u <- 0x%02x\n", reg, val));
! 1946: }
! 1947:
! 1948: uint8_t
! 1949: rt2661_bbp_read(struct rt2661_softc *sc, uint8_t reg)
! 1950: {
! 1951: uint32_t val;
! 1952: int ntries;
! 1953:
! 1954: for (ntries = 0; ntries < 100; ntries++) {
! 1955: if (!(RAL_READ(sc, RT2661_PHY_CSR3) & RT2661_BBP_BUSY))
! 1956: break;
! 1957: DELAY(1);
! 1958: }
! 1959: if (ntries == 100) {
! 1960: printf("%s: could not read from BBP\n", sc->sc_dev.dv_xname);
! 1961: return 0;
! 1962: }
! 1963:
! 1964: val = RT2661_BBP_BUSY | RT2661_BBP_READ | reg << 8;
! 1965: RAL_WRITE(sc, RT2661_PHY_CSR3, val);
! 1966:
! 1967: for (ntries = 0; ntries < 100; ntries++) {
! 1968: val = RAL_READ(sc, RT2661_PHY_CSR3);
! 1969: if (!(val & RT2661_BBP_BUSY))
! 1970: return val & 0xff;
! 1971: DELAY(1);
! 1972: }
! 1973:
! 1974: printf("%s: could not read from BBP\n", sc->sc_dev.dv_xname);
! 1975: return 0;
! 1976: }
! 1977:
! 1978: void
! 1979: rt2661_rf_write(struct rt2661_softc *sc, uint8_t reg, uint32_t val)
! 1980: {
! 1981: uint32_t tmp;
! 1982: int ntries;
! 1983:
! 1984: for (ntries = 0; ntries < 100; ntries++) {
! 1985: if (!(RAL_READ(sc, RT2661_PHY_CSR4) & RT2661_RF_BUSY))
! 1986: break;
! 1987: DELAY(1);
! 1988: }
! 1989: if (ntries == 100) {
! 1990: printf("%s: could not write to RF\n", sc->sc_dev.dv_xname);
! 1991: return;
! 1992: }
! 1993:
! 1994: tmp = RT2661_RF_BUSY | RT2661_RF_21BIT | (val & 0x1fffff) << 2 |
! 1995: (reg & 3);
! 1996: RAL_WRITE(sc, RT2661_PHY_CSR4, tmp);
! 1997:
! 1998: /* remember last written value in sc */
! 1999: sc->rf_regs[reg] = val;
! 2000:
! 2001: DPRINTFN(15, ("RF R[%u] <- 0x%05x\n", reg & 3, val & 0x1fffff));
! 2002: }
! 2003:
! 2004: int
! 2005: rt2661_tx_cmd(struct rt2661_softc *sc, uint8_t cmd, uint16_t arg)
! 2006: {
! 2007: if (RAL_READ(sc, RT2661_H2M_MAILBOX_CSR) & RT2661_H2M_BUSY)
! 2008: return EIO; /* there is already a command pending */
! 2009:
! 2010: RAL_WRITE(sc, RT2661_H2M_MAILBOX_CSR,
! 2011: RT2661_H2M_BUSY | RT2661_TOKEN_NO_INTR << 16 | arg);
! 2012:
! 2013: RAL_WRITE(sc, RT2661_HOST_CMD_CSR, RT2661_KICK_CMD | cmd);
! 2014:
! 2015: return 0;
! 2016: }
! 2017:
! 2018: void
! 2019: rt2661_select_antenna(struct rt2661_softc *sc)
! 2020: {
! 2021: uint8_t bbp4, bbp77;
! 2022: uint32_t tmp;
! 2023:
! 2024: bbp4 = rt2661_bbp_read(sc, 4);
! 2025: bbp77 = rt2661_bbp_read(sc, 77);
! 2026:
! 2027: /* TBD */
! 2028:
! 2029: /* make sure Rx is disabled before switching antenna */
! 2030: tmp = RAL_READ(sc, RT2661_TXRX_CSR0);
! 2031: RAL_WRITE(sc, RT2661_TXRX_CSR0, tmp | RT2661_DISABLE_RX);
! 2032:
! 2033: rt2661_bbp_write(sc, 4, bbp4);
! 2034: rt2661_bbp_write(sc, 77, bbp77);
! 2035:
! 2036: /* restore Rx filter */
! 2037: RAL_WRITE(sc, RT2661_TXRX_CSR0, tmp);
! 2038: }
! 2039:
! 2040: /*
! 2041: * Enable multi-rate retries for frames sent at OFDM rates.
! 2042: * In 802.11b/g mode, allow fallback to CCK rates.
! 2043: */
! 2044: void
! 2045: rt2661_enable_mrr(struct rt2661_softc *sc)
! 2046: {
! 2047: struct ieee80211com *ic = &sc->sc_ic;
! 2048: uint32_t tmp;
! 2049:
! 2050: tmp = RAL_READ(sc, RT2661_TXRX_CSR4);
! 2051:
! 2052: tmp &= ~RT2661_MRR_CCK_FALLBACK;
! 2053: if (!IEEE80211_IS_CHAN_5GHZ(ic->ic_bss->ni_chan))
! 2054: tmp |= RT2661_MRR_CCK_FALLBACK;
! 2055: tmp |= RT2661_MRR_ENABLED;
! 2056:
! 2057: RAL_WRITE(sc, RT2661_TXRX_CSR4, tmp);
! 2058: }
! 2059:
! 2060: void
! 2061: rt2661_set_txpreamble(struct rt2661_softc *sc)
! 2062: {
! 2063: uint32_t tmp;
! 2064:
! 2065: tmp = RAL_READ(sc, RT2661_TXRX_CSR4);
! 2066:
! 2067: tmp &= ~RT2661_SHORT_PREAMBLE;
! 2068: if (sc->sc_ic.ic_flags & IEEE80211_F_SHPREAMBLE)
! 2069: tmp |= RT2661_SHORT_PREAMBLE;
! 2070:
! 2071: RAL_WRITE(sc, RT2661_TXRX_CSR4, tmp);
! 2072: }
! 2073:
! 2074: void
! 2075: rt2661_set_basicrates(struct rt2661_softc *sc)
! 2076: {
! 2077: struct ieee80211com *ic = &sc->sc_ic;
! 2078:
! 2079: /* update basic rate set */
! 2080: if (ic->ic_curmode == IEEE80211_MODE_11B) {
! 2081: /* 11b basic rates: 1, 2Mbps */
! 2082: RAL_WRITE(sc, RT2661_TXRX_CSR5, 0x3);
! 2083: } else if (ic->ic_curmode == IEEE80211_MODE_11A) {
! 2084: /* 11a basic rates: 6, 12, 24Mbps */
! 2085: RAL_WRITE(sc, RT2661_TXRX_CSR5, 0x150);
! 2086: } else {
! 2087: /* 11b/g basic rates: 1, 2, 5.5, 11Mbps */
! 2088: RAL_WRITE(sc, RT2661_TXRX_CSR5, 0xf);
! 2089: }
! 2090: }
! 2091:
! 2092: /*
! 2093: * Reprogram MAC/BBP to switch to a new band. Values taken from the reference
! 2094: * driver.
! 2095: */
! 2096: void
! 2097: rt2661_select_band(struct rt2661_softc *sc, struct ieee80211_channel *c)
! 2098: {
! 2099: uint8_t bbp17, bbp35, bbp96, bbp97, bbp98, bbp104;
! 2100: uint32_t tmp;
! 2101:
! 2102: /* update all BBP registers that depend on the band */
! 2103: bbp17 = 0x20; bbp96 = 0x48; bbp104 = 0x2c;
! 2104: bbp35 = 0x50; bbp97 = 0x48; bbp98 = 0x48;
! 2105: if (IEEE80211_IS_CHAN_5GHZ(c)) {
! 2106: bbp17 += 0x08; bbp96 += 0x10; bbp104 += 0x0c;
! 2107: bbp35 += 0x10; bbp97 += 0x10; bbp98 += 0x10;
! 2108: }
! 2109: if ((IEEE80211_IS_CHAN_2GHZ(c) && sc->ext_2ghz_lna) ||
! 2110: (IEEE80211_IS_CHAN_5GHZ(c) && sc->ext_5ghz_lna)) {
! 2111: bbp17 += 0x10; bbp96 += 0x10; bbp104 += 0x10;
! 2112: }
! 2113:
! 2114: sc->bbp17 = bbp17;
! 2115: rt2661_bbp_write(sc, 17, bbp17);
! 2116: rt2661_bbp_write(sc, 96, bbp96);
! 2117: rt2661_bbp_write(sc, 104, bbp104);
! 2118:
! 2119: if ((IEEE80211_IS_CHAN_2GHZ(c) && sc->ext_2ghz_lna) ||
! 2120: (IEEE80211_IS_CHAN_5GHZ(c) && sc->ext_5ghz_lna)) {
! 2121: rt2661_bbp_write(sc, 75, 0x80);
! 2122: rt2661_bbp_write(sc, 86, 0x80);
! 2123: rt2661_bbp_write(sc, 88, 0x80);
! 2124: }
! 2125:
! 2126: rt2661_bbp_write(sc, 35, bbp35);
! 2127: rt2661_bbp_write(sc, 97, bbp97);
! 2128: rt2661_bbp_write(sc, 98, bbp98);
! 2129:
! 2130: tmp = RAL_READ(sc, RT2661_PHY_CSR0);
! 2131: tmp &= ~(RT2661_PA_PE_2GHZ | RT2661_PA_PE_5GHZ);
! 2132: if (IEEE80211_IS_CHAN_2GHZ(c))
! 2133: tmp |= RT2661_PA_PE_2GHZ;
! 2134: else
! 2135: tmp |= RT2661_PA_PE_5GHZ;
! 2136: RAL_WRITE(sc, RT2661_PHY_CSR0, tmp);
! 2137:
! 2138: /* 802.11a uses a 16 microseconds short interframe space */
! 2139: sc->sifs = IEEE80211_IS_CHAN_5GHZ(c) ? 16 : 10;
! 2140: }
! 2141:
! 2142: void
! 2143: rt2661_set_chan(struct rt2661_softc *sc, struct ieee80211_channel *c)
! 2144: {
! 2145: struct ieee80211com *ic = &sc->sc_ic;
! 2146: const struct rfprog *rfprog;
! 2147: uint8_t bbp3, bbp94 = RT2661_BBPR94_DEFAULT;
! 2148: int8_t power;
! 2149: u_int i, chan;
! 2150:
! 2151: chan = ieee80211_chan2ieee(ic, c);
! 2152: if (chan == 0 || chan == IEEE80211_CHAN_ANY)
! 2153: return;
! 2154:
! 2155: /* select the appropriate RF settings based on what EEPROM says */
! 2156: rfprog = (sc->rfprog == 0) ? rt2661_rf5225_1 : rt2661_rf5225_2;
! 2157:
! 2158: /* find the settings for this channel (we know it exists) */
! 2159: for (i = 0; rfprog[i].chan != chan; i++);
! 2160:
! 2161: power = sc->txpow[i];
! 2162: if (power < 0) {
! 2163: bbp94 += power;
! 2164: power = 0;
! 2165: } else if (power > 31) {
! 2166: bbp94 += power - 31;
! 2167: power = 31;
! 2168: }
! 2169:
! 2170: /*
! 2171: * If we are switching from the 2GHz band to the 5GHz band or
! 2172: * vice-versa, BBP registers need to be reprogrammed.
! 2173: */
! 2174: if (c->ic_flags != sc->sc_curchan->ic_flags) {
! 2175: rt2661_select_band(sc, c);
! 2176: rt2661_select_antenna(sc);
! 2177: }
! 2178: sc->sc_curchan = c;
! 2179:
! 2180: rt2661_rf_write(sc, RAL_RF1, rfprog[i].r1);
! 2181: rt2661_rf_write(sc, RAL_RF2, rfprog[i].r2);
! 2182: rt2661_rf_write(sc, RAL_RF3, rfprog[i].r3 | power << 7);
! 2183: rt2661_rf_write(sc, RAL_RF4, rfprog[i].r4 | sc->rffreq << 10);
! 2184:
! 2185: DELAY(200);
! 2186:
! 2187: rt2661_rf_write(sc, RAL_RF1, rfprog[i].r1);
! 2188: rt2661_rf_write(sc, RAL_RF2, rfprog[i].r2);
! 2189: rt2661_rf_write(sc, RAL_RF3, rfprog[i].r3 | power << 7 | 1);
! 2190: rt2661_rf_write(sc, RAL_RF4, rfprog[i].r4 | sc->rffreq << 10);
! 2191:
! 2192: DELAY(200);
! 2193:
! 2194: rt2661_rf_write(sc, RAL_RF1, rfprog[i].r1);
! 2195: rt2661_rf_write(sc, RAL_RF2, rfprog[i].r2);
! 2196: rt2661_rf_write(sc, RAL_RF3, rfprog[i].r3 | power << 7);
! 2197: rt2661_rf_write(sc, RAL_RF4, rfprog[i].r4 | sc->rffreq << 10);
! 2198:
! 2199: /* enable smart mode for MIMO-capable RFs */
! 2200: bbp3 = rt2661_bbp_read(sc, 3);
! 2201:
! 2202: bbp3 &= ~RT2661_SMART_MODE;
! 2203: if (sc->rf_rev == RT2661_RF_5325 || sc->rf_rev == RT2661_RF_2529)
! 2204: bbp3 |= RT2661_SMART_MODE;
! 2205:
! 2206: rt2661_bbp_write(sc, 3, bbp3);
! 2207:
! 2208: if (bbp94 != RT2661_BBPR94_DEFAULT)
! 2209: rt2661_bbp_write(sc, 94, bbp94);
! 2210:
! 2211: /* 5GHz radio needs a 1ms delay here */
! 2212: if (IEEE80211_IS_CHAN_5GHZ(c))
! 2213: DELAY(1000);
! 2214: }
! 2215:
! 2216: void
! 2217: rt2661_set_bssid(struct rt2661_softc *sc, const uint8_t *bssid)
! 2218: {
! 2219: uint32_t tmp;
! 2220:
! 2221: tmp = bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24;
! 2222: RAL_WRITE(sc, RT2661_MAC_CSR4, tmp);
! 2223:
! 2224: tmp = bssid[4] | bssid[5] << 8 | RT2661_ONE_BSSID << 16;
! 2225: RAL_WRITE(sc, RT2661_MAC_CSR5, tmp);
! 2226: }
! 2227:
! 2228: void
! 2229: rt2661_set_macaddr(struct rt2661_softc *sc, const uint8_t *addr)
! 2230: {
! 2231: uint32_t tmp;
! 2232:
! 2233: tmp = addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24;
! 2234: RAL_WRITE(sc, RT2661_MAC_CSR2, tmp);
! 2235:
! 2236: tmp = addr[4] | addr[5] << 8 | 0xff << 16;
! 2237: RAL_WRITE(sc, RT2661_MAC_CSR3, tmp);
! 2238: }
! 2239:
! 2240: void
! 2241: rt2661_update_promisc(struct rt2661_softc *sc)
! 2242: {
! 2243: struct ifnet *ifp = &sc->sc_ic.ic_if;
! 2244: uint32_t tmp;
! 2245:
! 2246: tmp = RAL_READ(sc, RT2661_TXRX_CSR0);
! 2247:
! 2248: tmp &= ~RT2661_DROP_NOT_TO_ME;
! 2249: if (!(ifp->if_flags & IFF_PROMISC))
! 2250: tmp |= RT2661_DROP_NOT_TO_ME;
! 2251:
! 2252: RAL_WRITE(sc, RT2661_TXRX_CSR0, tmp);
! 2253:
! 2254: DPRINTF(("%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ?
! 2255: "entering" : "leaving"));
! 2256: }
! 2257:
! 2258: void
! 2259: rt2661_updateslot(struct ieee80211com *ic)
! 2260: {
! 2261: struct rt2661_softc *sc = ic->ic_if.if_softc;
! 2262:
! 2263: if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
! 2264: /*
! 2265: * In HostAP mode, we defer setting of new slot time until
! 2266: * updated ERP Information Element has propagated to all
! 2267: * associated STAs.
! 2268: */
! 2269: sc->sc_flags |= RT2661_UPDATE_SLOT;
! 2270: } else
! 2271: rt2661_set_slottime(sc);
! 2272: }
! 2273:
! 2274: void
! 2275: rt2661_set_slottime(struct rt2661_softc *sc)
! 2276: {
! 2277: struct ieee80211com *ic = &sc->sc_ic;
! 2278: uint8_t slottime;
! 2279: uint32_t tmp;
! 2280:
! 2281: slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
! 2282:
! 2283: tmp = RAL_READ(sc, RT2661_MAC_CSR9);
! 2284: tmp = (tmp & ~0xff) | slottime;
! 2285: RAL_WRITE(sc, RT2661_MAC_CSR9, tmp);
! 2286:
! 2287: DPRINTF(("setting slot time to %uus\n", slottime));
! 2288: }
! 2289:
! 2290: const char *
! 2291: rt2661_get_rf(int rev)
! 2292: {
! 2293: switch (rev) {
! 2294: case RT2661_RF_5225: return "RT5225";
! 2295: case RT2661_RF_5325: return "RT5325 (MIMO XR)";
! 2296: case RT2661_RF_2527: return "RT2527";
! 2297: case RT2661_RF_2529: return "RT2529 (MIMO XR)";
! 2298: default: return "unknown";
! 2299: }
! 2300: }
! 2301:
! 2302: void
! 2303: rt2661_read_eeprom(struct rt2661_softc *sc)
! 2304: {
! 2305: struct ieee80211com *ic = &sc->sc_ic;
! 2306: uint16_t val;
! 2307: int i;
! 2308:
! 2309: /* read MAC address */
! 2310: val = rt2661_eeprom_read(sc, RT2661_EEPROM_MAC01);
! 2311: ic->ic_myaddr[0] = val & 0xff;
! 2312: ic->ic_myaddr[1] = val >> 8;
! 2313:
! 2314: val = rt2661_eeprom_read(sc, RT2661_EEPROM_MAC23);
! 2315: ic->ic_myaddr[2] = val & 0xff;
! 2316: ic->ic_myaddr[3] = val >> 8;
! 2317:
! 2318: val = rt2661_eeprom_read(sc, RT2661_EEPROM_MAC45);
! 2319: ic->ic_myaddr[4] = val & 0xff;
! 2320: ic->ic_myaddr[5] = val >> 8;
! 2321:
! 2322: val = rt2661_eeprom_read(sc, RT2661_EEPROM_ANTENNA);
! 2323: /* XXX: test if different from 0xffff? */
! 2324: sc->rf_rev = (val >> 11) & 0x1f;
! 2325: sc->hw_radio = (val >> 10) & 0x1;
! 2326: sc->rx_ant = (val >> 4) & 0x3;
! 2327: sc->tx_ant = (val >> 2) & 0x3;
! 2328: sc->nb_ant = val & 0x3;
! 2329:
! 2330: DPRINTF(("RF revision=%d\n", sc->rf_rev));
! 2331:
! 2332: val = rt2661_eeprom_read(sc, RT2661_EEPROM_CONFIG2);
! 2333: sc->ext_5ghz_lna = (val >> 6) & 0x1;
! 2334: sc->ext_2ghz_lna = (val >> 4) & 0x1;
! 2335:
! 2336: DPRINTF(("External 2GHz LNA=%d\nExternal 5GHz LNA=%d\n",
! 2337: sc->ext_2ghz_lna, sc->ext_5ghz_lna));
! 2338:
! 2339: val = rt2661_eeprom_read(sc, RT2661_EEPROM_RSSI_2GHZ_OFFSET);
! 2340: if ((val & 0xff) != 0xff)
! 2341: sc->rssi_2ghz_corr = (int8_t)(val & 0xff); /* signed */
! 2342:
! 2343: val = rt2661_eeprom_read(sc, RT2661_EEPROM_RSSI_5GHZ_OFFSET);
! 2344: if ((val & 0xff) != 0xff)
! 2345: sc->rssi_5ghz_corr = (int8_t)(val & 0xff); /* signed */
! 2346:
! 2347: /* adjust RSSI correction for external low-noise amplifier */
! 2348: if (sc->ext_2ghz_lna)
! 2349: sc->rssi_2ghz_corr -= 14;
! 2350: if (sc->ext_5ghz_lna)
! 2351: sc->rssi_5ghz_corr -= 14;
! 2352:
! 2353: DPRINTF(("RSSI 2GHz corr=%d\nRSSI 5GHz corr=%d\n",
! 2354: sc->rssi_2ghz_corr, sc->rssi_5ghz_corr));
! 2355:
! 2356: val = rt2661_eeprom_read(sc, RT2661_EEPROM_FREQ_OFFSET);
! 2357: if ((val >> 8) != 0xff)
! 2358: sc->rfprog = (val >> 8) & 0x3;
! 2359: if ((val & 0xff) != 0xff)
! 2360: sc->rffreq = val & 0xff;
! 2361:
! 2362: DPRINTF(("RF prog=%d\nRF freq=%d\n", sc->rfprog, sc->rffreq));
! 2363:
! 2364: /* read Tx power for all a/b/g channels */
! 2365: for (i = 0; i < 19; i++) {
! 2366: val = rt2661_eeprom_read(sc, RT2661_EEPROM_TXPOWER + i);
! 2367: sc->txpow[i * 2] = (int8_t)(val >> 8); /* signed */
! 2368: DPRINTF(("Channel=%d Tx power=%d\n",
! 2369: rt2661_rf5225_1[i * 2].chan, sc->txpow[i * 2]));
! 2370: sc->txpow[i * 2 + 1] = (int8_t)(val & 0xff); /* signed */
! 2371: DPRINTF(("Channel=%d Tx power=%d\n",
! 2372: rt2661_rf5225_1[i * 2 + 1].chan, sc->txpow[i * 2 + 1]));
! 2373: }
! 2374:
! 2375: /* read vendor-specific BBP values */
! 2376: for (i = 0; i < 16; i++) {
! 2377: val = rt2661_eeprom_read(sc, RT2661_EEPROM_BBP_BASE + i);
! 2378: if (val == 0 || val == 0xffff)
! 2379: continue; /* skip invalid entries */
! 2380: sc->bbp_prom[i].reg = val >> 8;
! 2381: sc->bbp_prom[i].val = val & 0xff;
! 2382: DPRINTF(("BBP R%d=%02x\n", sc->bbp_prom[i].reg,
! 2383: sc->bbp_prom[i].val));
! 2384: }
! 2385: }
! 2386:
! 2387: int
! 2388: rt2661_bbp_init(struct rt2661_softc *sc)
! 2389: {
! 2390: #define N(a) (sizeof (a) / sizeof ((a)[0]))
! 2391: int i, ntries;
! 2392:
! 2393: /* wait for BBP to be ready */
! 2394: for (ntries = 0; ntries < 100; ntries++) {
! 2395: const uint8_t val = rt2661_bbp_read(sc, 0);
! 2396: if (val != 0 && val != 0xff)
! 2397: break;
! 2398: DELAY(100);
! 2399: }
! 2400: if (ntries == 100) {
! 2401: printf("%s: timeout waiting for BBP\n", sc->sc_dev.dv_xname);
! 2402: return EIO;
! 2403: }
! 2404:
! 2405: /* initialize BBP registers to default values */
! 2406: for (i = 0; i < N(rt2661_def_bbp); i++) {
! 2407: rt2661_bbp_write(sc, rt2661_def_bbp[i].reg,
! 2408: rt2661_def_bbp[i].val);
! 2409: }
! 2410:
! 2411: /* write vendor-specific BBP values (from EEPROM) */
! 2412: for (i = 0; i < 16; i++) {
! 2413: if (sc->bbp_prom[i].reg == 0)
! 2414: continue;
! 2415: rt2661_bbp_write(sc, sc->bbp_prom[i].reg, sc->bbp_prom[i].val);
! 2416: }
! 2417:
! 2418: return 0;
! 2419: #undef N
! 2420: }
! 2421:
! 2422: int
! 2423: rt2661_init(struct ifnet *ifp)
! 2424: {
! 2425: #define N(a) (sizeof (a) / sizeof ((a)[0]))
! 2426: struct rt2661_softc *sc = ifp->if_softc;
! 2427: struct ieee80211com *ic = &sc->sc_ic;
! 2428: const char *name = NULL; /* make lint happy */
! 2429: uint8_t *ucode;
! 2430: size_t size;
! 2431: uint32_t tmp, sta[3];
! 2432: int i, ntries;
! 2433:
! 2434: /* for CardBus, power on the socket */
! 2435: if (!(sc->sc_flags & RT2661_ENABLED)) {
! 2436: if (sc->sc_enable != NULL && (*sc->sc_enable)(sc) != 0) {
! 2437: printf("%s: could not enable device\n",
! 2438: sc->sc_dev.dv_xname);
! 2439: return EIO;
! 2440: }
! 2441: sc->sc_flags |= RT2661_ENABLED;
! 2442: }
! 2443:
! 2444: rt2661_stop(ifp, 0);
! 2445:
! 2446: if (!(sc->sc_flags & RT2661_FWLOADED)) {
! 2447: switch (sc->sc_id) {
! 2448: case PCI_PRODUCT_RALINK_RT2561:
! 2449: name = "ral-rt2561";
! 2450: break;
! 2451: case PCI_PRODUCT_RALINK_RT2561S:
! 2452: name = "ral-rt2561s";
! 2453: break;
! 2454: case PCI_PRODUCT_RALINK_RT2661:
! 2455: name = "ral-rt2661";
! 2456: break;
! 2457: }
! 2458:
! 2459: if (loadfirmware(name, &ucode, &size) != 0) {
! 2460: printf("%s: could not read microcode %s\n",
! 2461: sc->sc_dev.dv_xname, name);
! 2462: rt2661_stop(ifp, 1);
! 2463: return EIO;
! 2464: }
! 2465:
! 2466: if (rt2661_load_microcode(sc, ucode, size) != 0) {
! 2467: printf("%s: could not load 8051 microcode\n",
! 2468: sc->sc_dev.dv_xname);
! 2469: free(ucode, M_DEVBUF);
! 2470: rt2661_stop(ifp, 1);
! 2471: return EIO;
! 2472: }
! 2473:
! 2474: free(ucode, M_DEVBUF);
! 2475: sc->sc_flags |= RT2661_FWLOADED;
! 2476: }
! 2477:
! 2478: /* initialize Tx rings */
! 2479: RAL_WRITE(sc, RT2661_AC1_BASE_CSR, sc->txq[1].physaddr);
! 2480: RAL_WRITE(sc, RT2661_AC0_BASE_CSR, sc->txq[0].physaddr);
! 2481: RAL_WRITE(sc, RT2661_AC2_BASE_CSR, sc->txq[2].physaddr);
! 2482: RAL_WRITE(sc, RT2661_AC3_BASE_CSR, sc->txq[3].physaddr);
! 2483:
! 2484: /* initialize Mgt ring */
! 2485: RAL_WRITE(sc, RT2661_MGT_BASE_CSR, sc->mgtq.physaddr);
! 2486:
! 2487: /* initialize Rx ring */
! 2488: RAL_WRITE(sc, RT2661_RX_BASE_CSR, sc->rxq.physaddr);
! 2489:
! 2490: /* initialize Tx rings sizes */
! 2491: RAL_WRITE(sc, RT2661_TX_RING_CSR0,
! 2492: RT2661_TX_RING_COUNT << 24 |
! 2493: RT2661_TX_RING_COUNT << 16 |
! 2494: RT2661_TX_RING_COUNT << 8 |
! 2495: RT2661_TX_RING_COUNT);
! 2496:
! 2497: RAL_WRITE(sc, RT2661_TX_RING_CSR1,
! 2498: RT2661_TX_DESC_WSIZE << 16 |
! 2499: RT2661_TX_RING_COUNT << 8 | /* XXX: HCCA ring unused */
! 2500: RT2661_MGT_RING_COUNT);
! 2501:
! 2502: /* initialize Rx rings */
! 2503: RAL_WRITE(sc, RT2661_RX_RING_CSR,
! 2504: RT2661_RX_DESC_BACK << 16 |
! 2505: RT2661_RX_DESC_WSIZE << 8 |
! 2506: RT2661_RX_RING_COUNT);
! 2507:
! 2508: /* XXX: some magic here */
! 2509: RAL_WRITE(sc, RT2661_TX_DMA_DST_CSR, 0xaa);
! 2510:
! 2511: /* load base addresses of all 5 Tx rings (4 data + 1 mgt) */
! 2512: RAL_WRITE(sc, RT2661_LOAD_TX_RING_CSR, 0x1f);
! 2513:
! 2514: /* load base address of Rx ring */
! 2515: RAL_WRITE(sc, RT2661_RX_CNTL_CSR, 2);
! 2516:
! 2517: /* initialize MAC registers to default values */
! 2518: for (i = 0; i < N(rt2661_def_mac); i++)
! 2519: RAL_WRITE(sc, rt2661_def_mac[i].reg, rt2661_def_mac[i].val);
! 2520:
! 2521: IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));
! 2522: rt2661_set_macaddr(sc, ic->ic_myaddr);
! 2523:
! 2524: /* set host ready */
! 2525: RAL_WRITE(sc, RT2661_MAC_CSR1, 3);
! 2526: RAL_WRITE(sc, RT2661_MAC_CSR1, 0);
! 2527:
! 2528: /* wait for BBP/RF to wakeup */
! 2529: for (ntries = 0; ntries < 1000; ntries++) {
! 2530: if (RAL_READ(sc, RT2661_MAC_CSR12) & 8)
! 2531: break;
! 2532: DELAY(1000);
! 2533: }
! 2534: if (ntries == 1000) {
! 2535: printf("timeout waiting for BBP/RF to wakeup\n");
! 2536: rt2661_stop(ifp, 1);
! 2537: return EIO;
! 2538: }
! 2539:
! 2540: if (rt2661_bbp_init(sc) != 0) {
! 2541: rt2661_stop(ifp, 1);
! 2542: return EIO;
! 2543: }
! 2544:
! 2545: /* select default channel */
! 2546: sc->sc_curchan = ic->ic_bss->ni_chan = ic->ic_ibss_chan;
! 2547: rt2661_select_band(sc, sc->sc_curchan);
! 2548: rt2661_select_antenna(sc);
! 2549: rt2661_set_chan(sc, sc->sc_curchan);
! 2550:
! 2551: /* update Rx filter */
! 2552: tmp = RAL_READ(sc, RT2661_TXRX_CSR0) & 0xffff;
! 2553:
! 2554: tmp |= RT2661_DROP_PHY_ERROR | RT2661_DROP_CRC_ERROR;
! 2555: if (ic->ic_opmode != IEEE80211_M_MONITOR) {
! 2556: tmp |= RT2661_DROP_CTL | RT2661_DROP_VER_ERROR |
! 2557: RT2661_DROP_ACKCTS;
! 2558: if (ic->ic_opmode != IEEE80211_M_HOSTAP)
! 2559: tmp |= RT2661_DROP_TODS;
! 2560: if (!(ifp->if_flags & IFF_PROMISC))
! 2561: tmp |= RT2661_DROP_NOT_TO_ME;
! 2562: }
! 2563:
! 2564: RAL_WRITE(sc, RT2661_TXRX_CSR0, tmp);
! 2565:
! 2566: /* clear STA registers */
! 2567: RAL_READ_REGION_4(sc, RT2661_STA_CSR0, sta, N(sta));
! 2568:
! 2569: /* initialize ASIC */
! 2570: RAL_WRITE(sc, RT2661_MAC_CSR1, 4);
! 2571:
! 2572: /* clear any pending interrupt */
! 2573: RAL_WRITE(sc, RT2661_INT_SOURCE_CSR, 0xffffffff);
! 2574:
! 2575: /* enable interrupts */
! 2576: RAL_WRITE(sc, RT2661_INT_MASK_CSR, 0x0000ff10);
! 2577: RAL_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0);
! 2578:
! 2579: /* kick Rx */
! 2580: RAL_WRITE(sc, RT2661_RX_CNTL_CSR, 1);
! 2581:
! 2582: ifp->if_flags &= ~IFF_OACTIVE;
! 2583: ifp->if_flags |= IFF_RUNNING;
! 2584:
! 2585: if (ic->ic_opmode != IEEE80211_M_MONITOR)
! 2586: ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
! 2587: else
! 2588: ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
! 2589:
! 2590: return 0;
! 2591: #undef N
! 2592: }
! 2593:
! 2594: void
! 2595: rt2661_stop(struct ifnet *ifp, int disable)
! 2596: {
! 2597: struct rt2661_softc *sc = ifp->if_softc;
! 2598: struct ieee80211com *ic = &sc->sc_ic;
! 2599: uint32_t tmp;
! 2600: int ac;
! 2601:
! 2602: sc->sc_tx_timer = 0;
! 2603: ifp->if_timer = 0;
! 2604: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
! 2605:
! 2606: ieee80211_new_state(ic, IEEE80211_S_INIT, -1); /* free all nodes */
! 2607:
! 2608: /* abort Tx (for all 5 Tx rings) */
! 2609: RAL_WRITE(sc, RT2661_TX_CNTL_CSR, 0x1f << 16);
! 2610:
! 2611: /* disable Rx (value remains after reset!) */
! 2612: tmp = RAL_READ(sc, RT2661_TXRX_CSR0);
! 2613: RAL_WRITE(sc, RT2661_TXRX_CSR0, tmp | RT2661_DISABLE_RX);
! 2614:
! 2615: /* reset ASIC */
! 2616: RAL_WRITE(sc, RT2661_MAC_CSR1, 3);
! 2617: RAL_WRITE(sc, RT2661_MAC_CSR1, 0);
! 2618:
! 2619: /* disable interrupts */
! 2620: RAL_WRITE(sc, RT2661_INT_MASK_CSR, 0xffffff7f);
! 2621: RAL_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0xffffffff);
! 2622:
! 2623: /* clear any pending interrupt */
! 2624: RAL_WRITE(sc, RT2661_INT_SOURCE_CSR, 0xffffffff);
! 2625: RAL_WRITE(sc, RT2661_MCU_INT_SOURCE_CSR, 0xffffffff);
! 2626:
! 2627: /* reset Tx and Rx rings */
! 2628: for (ac = 0; ac < 4; ac++)
! 2629: rt2661_reset_tx_ring(sc, &sc->txq[ac]);
! 2630: rt2661_reset_tx_ring(sc, &sc->mgtq);
! 2631: rt2661_reset_rx_ring(sc, &sc->rxq);
! 2632:
! 2633: /* for CardBus, power down the socket */
! 2634: if (disable && sc->sc_disable != NULL) {
! 2635: if (sc->sc_flags & RT2661_ENABLED) {
! 2636: (*sc->sc_disable)(sc);
! 2637: sc->sc_flags &= ~(RT2661_ENABLED | RT2661_FWLOADED);
! 2638: }
! 2639: }
! 2640: }
! 2641:
! 2642: int
! 2643: rt2661_load_microcode(struct rt2661_softc *sc, const uint8_t *ucode, int size)
! 2644: {
! 2645: int ntries;
! 2646:
! 2647: /* reset 8051 */
! 2648: RAL_WRITE(sc, RT2661_MCU_CNTL_CSR, RT2661_MCU_RESET);
! 2649:
! 2650: /* cancel any pending Host to MCU command */
! 2651: RAL_WRITE(sc, RT2661_H2M_MAILBOX_CSR, 0);
! 2652: RAL_WRITE(sc, RT2661_M2H_CMD_DONE_CSR, 0xffffffff);
! 2653: RAL_WRITE(sc, RT2661_HOST_CMD_CSR, 0);
! 2654:
! 2655: /* write 8051's microcode */
! 2656: RAL_WRITE(sc, RT2661_MCU_CNTL_CSR, RT2661_MCU_RESET | RT2661_MCU_SEL);
! 2657: RAL_WRITE_REGION_1(sc, RT2661_MCU_CODE_BASE, ucode, size);
! 2658: RAL_WRITE(sc, RT2661_MCU_CNTL_CSR, RT2661_MCU_RESET);
! 2659:
! 2660: /* kick 8051's ass */
! 2661: RAL_WRITE(sc, RT2661_MCU_CNTL_CSR, 0);
! 2662:
! 2663: /* wait for 8051 to initialize */
! 2664: for (ntries = 0; ntries < 500; ntries++) {
! 2665: if (RAL_READ(sc, RT2661_MCU_CNTL_CSR) & RT2661_MCU_READY)
! 2666: break;
! 2667: DELAY(100);
! 2668: }
! 2669: if (ntries == 500) {
! 2670: printf("timeout waiting for MCU to initialize\n");
! 2671: return EIO;
! 2672: }
! 2673: return 0;
! 2674: }
! 2675:
! 2676: /*
! 2677: * Dynamically tune Rx sensitivity (BBP register 17) based on average RSSI and
! 2678: * false CCA count. This function is called periodically (every seconds) when
! 2679: * in the RUN state. Values taken from the reference driver.
! 2680: */
! 2681: void
! 2682: rt2661_rx_tune(struct rt2661_softc *sc)
! 2683: {
! 2684: uint8_t bbp17;
! 2685: uint16_t cca;
! 2686: int lo, hi, dbm;
! 2687:
! 2688: /*
! 2689: * Tuning range depends on operating band and on the presence of an
! 2690: * external low-noise amplifier.
! 2691: */
! 2692: lo = 0x20;
! 2693: if (IEEE80211_IS_CHAN_5GHZ(sc->sc_curchan))
! 2694: lo += 0x08;
! 2695: if ((IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan) && sc->ext_2ghz_lna) ||
! 2696: (IEEE80211_IS_CHAN_5GHZ(sc->sc_curchan) && sc->ext_5ghz_lna))
! 2697: lo += 0x10;
! 2698: hi = lo + 0x20;
! 2699:
! 2700: dbm = sc->avg_rssi;
! 2701: /* retrieve false CCA count since last call (clear on read) */
! 2702: cca = RAL_READ(sc, RT2661_STA_CSR1) & 0xffff;
! 2703:
! 2704: DPRINTFN(2, ("RSSI=%ddBm false CCA=%d\n", dbm, cca));
! 2705:
! 2706: if (dbm < -74) {
! 2707: /* very bad RSSI, tune using false CCA count */
! 2708: bbp17 = sc->bbp17; /* current value */
! 2709:
! 2710: hi -= 2 * (-74 - dbm);
! 2711: if (hi < lo)
! 2712: hi = lo;
! 2713:
! 2714: if (bbp17 > hi)
! 2715: bbp17 = hi;
! 2716: else if (cca > 512)
! 2717: bbp17 = min(bbp17 + 1, hi);
! 2718: else if (cca < 100)
! 2719: bbp17 = max(bbp17 - 1, lo);
! 2720:
! 2721: } else if (dbm < -66) {
! 2722: bbp17 = lo + 0x08;
! 2723: } else if (dbm < -58) {
! 2724: bbp17 = lo + 0x10;
! 2725: } else if (dbm < -35) {
! 2726: bbp17 = hi;
! 2727: } else { /* very good RSSI >= -35dBm */
! 2728: bbp17 = 0x60; /* very low sensitivity */
! 2729: }
! 2730:
! 2731: if (bbp17 != sc->bbp17) {
! 2732: DPRINTF(("BBP17 %x->%x\n", sc->bbp17, bbp17));
! 2733: rt2661_bbp_write(sc, 17, bbp17);
! 2734: sc->bbp17 = bbp17;
! 2735: }
! 2736: }
! 2737:
! 2738: #ifdef notyet
! 2739: /*
! 2740: * Enter/Leave radar detection mode.
! 2741: * This is for 802.11h additional regulatory domains.
! 2742: */
! 2743: void
! 2744: rt2661_radar_start(struct rt2661_softc *sc)
! 2745: {
! 2746: uint32_t tmp;
! 2747:
! 2748: /* disable Rx */
! 2749: tmp = RAL_READ(sc, RT2661_TXRX_CSR0);
! 2750: RAL_WRITE(sc, RT2661_TXRX_CSR0, tmp | RT2661_DISABLE_RX);
! 2751:
! 2752: rt2661_bbp_write(sc, 82, 0x20);
! 2753: rt2661_bbp_write(sc, 83, 0x00);
! 2754: rt2661_bbp_write(sc, 84, 0x40);
! 2755:
! 2756: /* save current BBP registers values */
! 2757: sc->bbp18 = rt2661_bbp_read(sc, 18);
! 2758: sc->bbp21 = rt2661_bbp_read(sc, 21);
! 2759: sc->bbp22 = rt2661_bbp_read(sc, 22);
! 2760: sc->bbp16 = rt2661_bbp_read(sc, 16);
! 2761: sc->bbp17 = rt2661_bbp_read(sc, 17);
! 2762: sc->bbp64 = rt2661_bbp_read(sc, 64);
! 2763:
! 2764: rt2661_bbp_write(sc, 18, 0xff);
! 2765: rt2661_bbp_write(sc, 21, 0x3f);
! 2766: rt2661_bbp_write(sc, 22, 0x3f);
! 2767: rt2661_bbp_write(sc, 16, 0xbd);
! 2768: rt2661_bbp_write(sc, 17, sc->ext_5ghz_lna ? 0x44 : 0x34);
! 2769: rt2661_bbp_write(sc, 64, 0x21);
! 2770:
! 2771: /* restore Rx filter */
! 2772: RAL_WRITE(sc, RT2661_TXRX_CSR0, tmp);
! 2773: }
! 2774:
! 2775: int
! 2776: rt2661_radar_stop(struct rt2661_softc *sc)
! 2777: {
! 2778: uint8_t bbp66;
! 2779:
! 2780: /* read radar detection result */
! 2781: bbp66 = rt2661_bbp_read(sc, 66);
! 2782:
! 2783: /* restore BBP registers values */
! 2784: rt2661_bbp_write(sc, 16, sc->bbp16);
! 2785: rt2661_bbp_write(sc, 17, sc->bbp17);
! 2786: rt2661_bbp_write(sc, 18, sc->bbp18);
! 2787: rt2661_bbp_write(sc, 21, sc->bbp21);
! 2788: rt2661_bbp_write(sc, 22, sc->bbp22);
! 2789: rt2661_bbp_write(sc, 64, sc->bbp64);
! 2790:
! 2791: return bbp66 == 1;
! 2792: }
! 2793: #endif
! 2794:
! 2795: int
! 2796: rt2661_prepare_beacon(struct rt2661_softc *sc)
! 2797: {
! 2798: struct ieee80211com *ic = &sc->sc_ic;
! 2799: struct ieee80211_node *ni = ic->ic_bss;
! 2800: struct rt2661_tx_desc desc;
! 2801: struct mbuf *m0;
! 2802: int rate;
! 2803:
! 2804: m0 = ieee80211_beacon_alloc(ic, ni);
! 2805: if (m0 == NULL) {
! 2806: printf("%s: could not allocate beacon frame\n",
! 2807: sc->sc_dev.dv_xname);
! 2808: return ENOBUFS;
! 2809: }
! 2810:
! 2811: /* send beacons at the lowest available rate */
! 2812: rate = IEEE80211_IS_CHAN_5GHZ(ni->ni_chan) ? 12 : 2;
! 2813:
! 2814: rt2661_setup_tx_desc(sc, &desc, RT2661_TX_TIMESTAMP, RT2661_TX_HWSEQ,
! 2815: m0->m_pkthdr.len, rate, NULL, 0, RT2661_QID_MGT);
! 2816:
! 2817: /* copy the first 24 bytes of Tx descriptor into NIC memory */
! 2818: RAL_WRITE_REGION_1(sc, RT2661_HW_BEACON_BASE0, (uint8_t *)&desc, 24);
! 2819:
! 2820: /* copy beacon header and payload into NIC memory */
! 2821: RAL_WRITE_REGION_1(sc, RT2661_HW_BEACON_BASE0 + 24,
! 2822: mtod(m0, uint8_t *), m0->m_pkthdr.len);
! 2823:
! 2824: m_freem(m0);
! 2825:
! 2826: /*
! 2827: * Store offset of ERP Information Element so that we can update it
! 2828: * dynamically when the slot time changes.
! 2829: * XXX: this is ugly since it depends on how net80211 builds beacon
! 2830: * frames but ieee80211_beacon_alloc() doesn't store offsets for us.
! 2831: */
! 2832: if (ic->ic_curmode == IEEE80211_MODE_11G) {
! 2833: sc->erp_csr =
! 2834: RT2661_HW_BEACON_BASE0 + 24 +
! 2835: sizeof (struct ieee80211_frame) +
! 2836: 8 + 2 + 2 +
! 2837: ((ic->ic_flags & IEEE80211_F_HIDENWID) ?
! 2838: 1 : 2 + ni->ni_esslen) +
! 2839: 2 + min(ni->ni_rates.rs_nrates, IEEE80211_RATE_SIZE) +
! 2840: 2 + 1 +
! 2841: ((ic->ic_opmode == IEEE80211_M_IBSS) ? 4 : 6) +
! 2842: 2;
! 2843: }
! 2844:
! 2845: return 0;
! 2846: }
! 2847:
! 2848: /*
! 2849: * Enable TSF synchronization and tell h/w to start sending beacons for IBSS
! 2850: * and HostAP operating modes.
! 2851: */
! 2852: void
! 2853: rt2661_enable_tsf_sync(struct rt2661_softc *sc)
! 2854: {
! 2855: struct ieee80211com *ic = &sc->sc_ic;
! 2856: uint32_t tmp;
! 2857:
! 2858: if (ic->ic_opmode != IEEE80211_M_STA) {
! 2859: /*
! 2860: * Change default 16ms TBTT adjustment to 8ms.
! 2861: * Must be done before enabling beacon generation.
! 2862: */
! 2863: RAL_WRITE(sc, RT2661_TXRX_CSR10, 1 << 12 | 8);
! 2864: }
! 2865:
! 2866: tmp = RAL_READ(sc, RT2661_TXRX_CSR9) & 0xff000000;
! 2867:
! 2868: /* set beacon interval (in 1/16ms unit) */
! 2869: tmp |= ic->ic_bss->ni_intval * 16;
! 2870:
! 2871: tmp |= RT2661_TSF_TICKING | RT2661_ENABLE_TBTT;
! 2872: if (ic->ic_opmode == IEEE80211_M_STA)
! 2873: tmp |= RT2661_TSF_MODE(1);
! 2874: else
! 2875: tmp |= RT2661_TSF_MODE(2) | RT2661_GENERATE_BEACON;
! 2876:
! 2877: RAL_WRITE(sc, RT2661_TXRX_CSR9, tmp);
! 2878: }
! 2879:
! 2880: /*
! 2881: * Retrieve the "Received Signal Strength Indicator" from the raw values
! 2882: * contained in Rx descriptors. The computation depends on which band the
! 2883: * frame was received. Correction values taken from the reference driver.
! 2884: */
! 2885: int
! 2886: rt2661_get_rssi(struct rt2661_softc *sc, uint8_t raw)
! 2887: {
! 2888: int lna, agc, rssi;
! 2889:
! 2890: lna = (raw >> 5) & 0x3;
! 2891: agc = raw & 0x1f;
! 2892:
! 2893: rssi = 2 * agc;
! 2894:
! 2895: if (IEEE80211_IS_CHAN_2GHZ(sc->sc_curchan)) {
! 2896: rssi += sc->rssi_2ghz_corr;
! 2897:
! 2898: if (lna == 1)
! 2899: rssi -= 64;
! 2900: else if (lna == 2)
! 2901: rssi -= 74;
! 2902: else if (lna == 3)
! 2903: rssi -= 90;
! 2904: } else {
! 2905: rssi += sc->rssi_5ghz_corr;
! 2906:
! 2907: if (lna == 1)
! 2908: rssi -= 64;
! 2909: else if (lna == 2)
! 2910: rssi -= 86;
! 2911: else if (lna == 3)
! 2912: rssi -= 100;
! 2913: }
! 2914: return rssi;
! 2915: }
! 2916:
! 2917: void
! 2918: rt2661_power(int why, void *arg)
! 2919: {
! 2920: struct rt2661_softc *sc = arg;
! 2921: struct ifnet *ifp = &sc->sc_ic.ic_if;
! 2922: int s;
! 2923:
! 2924: DPRINTF(("%s: rt2661_power(%d)\n", sc->sc_dev.dv_xname, why));
! 2925:
! 2926: s = splnet();
! 2927: switch (why) {
! 2928: case PWR_SUSPEND:
! 2929: case PWR_STANDBY:
! 2930: rt2661_stop(ifp, 1);
! 2931: sc->sc_flags &= ~RT2661_FWLOADED;
! 2932: if (sc->sc_power != NULL)
! 2933: (*sc->sc_power)(sc, why);
! 2934: break;
! 2935: case PWR_RESUME:
! 2936: if (ifp->if_flags & IFF_UP) {
! 2937: rt2661_init(ifp);
! 2938: if (sc->sc_power != NULL)
! 2939: (*sc->sc_power)(sc, why);
! 2940: if (ifp->if_flags & IFF_RUNNING)
! 2941: rt2661_start(ifp);
! 2942: }
! 2943: break;
! 2944: }
! 2945: splx(s);
! 2946: }
! 2947:
! 2948: void
! 2949: rt2661_shutdown(void *arg)
! 2950: {
! 2951: struct rt2661_softc *sc = arg;
! 2952: struct ifnet *ifp = &sc->sc_ic.ic_if;
! 2953:
! 2954: rt2661_stop(ifp, 1);
! 2955: }
CVSweb