Annotation of sys/dev/ic/rt2560.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: rt2560.c,v 1.32 2007/03/08 21:58:27 deraadt Exp $ */
! 2:
! 3: /*-
! 4: * Copyright (c) 2005, 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 RT2560 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/rt2560reg.h>
! 63: #include <dev/ic/rt2560var.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 (rt2560_debug > 0) printf x; } while (0)
! 71: #define DPRINTFN(n, x) do { if (rt2560_debug >= (n)) printf x; } while (0)
! 72: int rt2560_debug = 1;
! 73: #else
! 74: #define DPRINTF(x)
! 75: #define DPRINTFN(n, x)
! 76: #endif
! 77:
! 78: int rt2560_alloc_tx_ring(struct rt2560_softc *,
! 79: struct rt2560_tx_ring *, int);
! 80: void rt2560_reset_tx_ring(struct rt2560_softc *,
! 81: struct rt2560_tx_ring *);
! 82: void rt2560_free_tx_ring(struct rt2560_softc *,
! 83: struct rt2560_tx_ring *);
! 84: int rt2560_alloc_rx_ring(struct rt2560_softc *,
! 85: struct rt2560_rx_ring *, int);
! 86: void rt2560_reset_rx_ring(struct rt2560_softc *,
! 87: struct rt2560_rx_ring *);
! 88: void rt2560_free_rx_ring(struct rt2560_softc *,
! 89: struct rt2560_rx_ring *);
! 90: struct ieee80211_node *rt2560_node_alloc(struct ieee80211com *);
! 91: int rt2560_media_change(struct ifnet *);
! 92: void rt2560_next_scan(void *);
! 93: void rt2560_iter_func(void *, struct ieee80211_node *);
! 94: void rt2560_amrr_timeout(void *);
! 95: void rt2560_newassoc(struct ieee80211com *, struct ieee80211_node *,
! 96: int);
! 97: int rt2560_newstate(struct ieee80211com *, enum ieee80211_state,
! 98: int);
! 99: uint16_t rt2560_eeprom_read(struct rt2560_softc *, uint8_t);
! 100: void rt2560_encryption_intr(struct rt2560_softc *);
! 101: void rt2560_tx_intr(struct rt2560_softc *);
! 102: void rt2560_prio_intr(struct rt2560_softc *);
! 103: void rt2560_decryption_intr(struct rt2560_softc *);
! 104: void rt2560_rx_intr(struct rt2560_softc *);
! 105: void rt2560_beacon_expire(struct rt2560_softc *);
! 106: void rt2560_wakeup_expire(struct rt2560_softc *);
! 107: #if NBPFILTER > 0
! 108: uint8_t rt2560_rxrate(const struct rt2560_rx_desc *);
! 109: #endif
! 110: int rt2560_ack_rate(struct ieee80211com *, int);
! 111: uint16_t rt2560_txtime(int, int, uint32_t);
! 112: uint8_t rt2560_plcp_signal(int);
! 113: void rt2560_setup_tx_desc(struct rt2560_softc *,
! 114: struct rt2560_tx_desc *, uint32_t, int, int, int,
! 115: bus_addr_t);
! 116: int rt2560_tx_bcn(struct rt2560_softc *, struct mbuf *,
! 117: struct ieee80211_node *);
! 118: int rt2560_tx_mgt(struct rt2560_softc *, struct mbuf *,
! 119: struct ieee80211_node *);
! 120: int rt2560_tx_data(struct rt2560_softc *, struct mbuf *,
! 121: struct ieee80211_node *);
! 122: void rt2560_start(struct ifnet *);
! 123: void rt2560_watchdog(struct ifnet *);
! 124: int rt2560_ioctl(struct ifnet *, u_long, caddr_t);
! 125: void rt2560_bbp_write(struct rt2560_softc *, uint8_t, uint8_t);
! 126: uint8_t rt2560_bbp_read(struct rt2560_softc *, uint8_t);
! 127: void rt2560_rf_write(struct rt2560_softc *, uint8_t, uint32_t);
! 128: void rt2560_set_chan(struct rt2560_softc *,
! 129: struct ieee80211_channel *);
! 130: void rt2560_disable_rf_tune(struct rt2560_softc *);
! 131: void rt2560_enable_tsf_sync(struct rt2560_softc *);
! 132: void rt2560_update_plcp(struct rt2560_softc *);
! 133: void rt2560_updateslot(struct ieee80211com *);
! 134: void rt2560_set_slottime(struct rt2560_softc *);
! 135: void rt2560_set_basicrates(struct rt2560_softc *);
! 136: void rt2560_update_led(struct rt2560_softc *, int, int);
! 137: void rt2560_set_bssid(struct rt2560_softc *, uint8_t *);
! 138: void rt2560_set_macaddr(struct rt2560_softc *, uint8_t *);
! 139: void rt2560_get_macaddr(struct rt2560_softc *, uint8_t *);
! 140: void rt2560_update_promisc(struct rt2560_softc *);
! 141: void rt2560_set_txantenna(struct rt2560_softc *, int);
! 142: void rt2560_set_rxantenna(struct rt2560_softc *, int);
! 143: const char *rt2560_get_rf(int);
! 144: void rt2560_read_eeprom(struct rt2560_softc *);
! 145: int rt2560_bbp_init(struct rt2560_softc *);
! 146: int rt2560_init(struct ifnet *);
! 147: void rt2560_stop(struct ifnet *, int);
! 148: void rt2560_power(int, void *);
! 149:
! 150: static const struct {
! 151: uint32_t reg;
! 152: uint32_t val;
! 153: } rt2560_def_mac[] = {
! 154: RT2560_DEF_MAC
! 155: };
! 156:
! 157: static const struct {
! 158: uint8_t reg;
! 159: uint8_t val;
! 160: } rt2560_def_bbp[] = {
! 161: RT2560_DEF_BBP
! 162: };
! 163:
! 164: static const uint32_t rt2560_rf2522_r2[] = RT2560_RF2522_R2;
! 165: static const uint32_t rt2560_rf2523_r2[] = RT2560_RF2523_R2;
! 166: static const uint32_t rt2560_rf2524_r2[] = RT2560_RF2524_R2;
! 167: static const uint32_t rt2560_rf2525_r2[] = RT2560_RF2525_R2;
! 168: static const uint32_t rt2560_rf2525_hi_r2[] = RT2560_RF2525_HI_R2;
! 169: static const uint32_t rt2560_rf2525e_r2[] = RT2560_RF2525E_R2;
! 170: static const uint32_t rt2560_rf2526_r2[] = RT2560_RF2526_R2;
! 171: static const uint32_t rt2560_rf2526_hi_r2[] = RT2560_RF2526_HI_R2;
! 172:
! 173: int
! 174: rt2560_attach(void *xsc, int id)
! 175: {
! 176: struct rt2560_softc *sc = xsc;
! 177: struct ieee80211com *ic = &sc->sc_ic;
! 178: struct ifnet *ifp = &ic->ic_if;
! 179: int error, i;
! 180:
! 181: sc->amrr.amrr_min_success_threshold = 1;
! 182: sc->amrr.amrr_max_success_threshold = 15;
! 183: timeout_set(&sc->amrr_to, rt2560_amrr_timeout, sc);
! 184: timeout_set(&sc->scan_to, rt2560_next_scan, sc);
! 185:
! 186: /* retrieve RT2560 rev. no */
! 187: sc->asic_rev = RAL_READ(sc, RT2560_CSR0);
! 188:
! 189: /* retrieve MAC address */
! 190: rt2560_get_macaddr(sc, ic->ic_myaddr);
! 191: printf(", address %s\n", ether_sprintf(ic->ic_myaddr));
! 192:
! 193: /* retrieve RF rev. no and various other things from EEPROM */
! 194: rt2560_read_eeprom(sc);
! 195:
! 196: printf("%s: MAC/BBP RT2560 (rev 0x%02x), RF %s\n", sc->sc_dev.dv_xname,
! 197: sc->asic_rev, rt2560_get_rf(sc->rf_rev));
! 198:
! 199: /*
! 200: * Allocate Tx and Rx rings.
! 201: */
! 202: error = rt2560_alloc_tx_ring(sc, &sc->txq, RT2560_TX_RING_COUNT);
! 203: if (error != 0) {
! 204: printf("%s: could not allocate Tx ring\n",
! 205: sc->sc_dev.dv_xname);
! 206: goto fail1;
! 207: }
! 208: error = rt2560_alloc_tx_ring(sc, &sc->atimq, RT2560_ATIM_RING_COUNT);
! 209: if (error != 0) {
! 210: printf("%s: could not allocate ATIM ring\n",
! 211: sc->sc_dev.dv_xname);
! 212: goto fail2;
! 213: }
! 214: error = rt2560_alloc_tx_ring(sc, &sc->prioq, RT2560_PRIO_RING_COUNT);
! 215: if (error != 0) {
! 216: printf("%s: could not allocate Prio ring\n",
! 217: sc->sc_dev.dv_xname);
! 218: goto fail3;
! 219: }
! 220: error = rt2560_alloc_tx_ring(sc, &sc->bcnq, RT2560_BEACON_RING_COUNT);
! 221: if (error != 0) {
! 222: printf("%s: could not allocate Beacon ring\n",
! 223: sc->sc_dev.dv_xname);
! 224: goto fail4;
! 225: }
! 226: error = rt2560_alloc_rx_ring(sc, &sc->rxq, RT2560_RX_RING_COUNT);
! 227: if (error != 0) {
! 228: printf("%s: could not allocate Rx ring\n",
! 229: sc->sc_dev.dv_xname);
! 230: goto fail5;
! 231: }
! 232:
! 233: ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
! 234: ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
! 235: ic->ic_state = IEEE80211_S_INIT;
! 236:
! 237: /* set device capabilities */
! 238: ic->ic_caps =
! 239: IEEE80211_C_IBSS | /* IBSS mode supported */
! 240: IEEE80211_C_MONITOR | /* monitor mode supported */
! 241: IEEE80211_C_HOSTAP | /* HostAp mode supported */
! 242: IEEE80211_C_TXPMGT | /* tx power management */
! 243: IEEE80211_C_SHPREAMBLE | /* short preamble supported */
! 244: IEEE80211_C_SHSLOT | /* short slot time supported */
! 245: IEEE80211_C_WEP; /* s/w WEP */
! 246:
! 247: /* set supported .11b and .11g rates */
! 248: ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
! 249: ic->ic_sup_rates[IEEE80211_MODE_11G] = ieee80211_std_rateset_11g;
! 250:
! 251: /* set supported .11b and .11g channels (1 through 14) */
! 252: for (i = 1; i <= 14; i++) {
! 253: ic->ic_channels[i].ic_freq =
! 254: ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
! 255: ic->ic_channels[i].ic_flags =
! 256: IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
! 257: IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
! 258: }
! 259:
! 260: ifp->if_softc = sc;
! 261: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
! 262: ifp->if_init = rt2560_init;
! 263: ifp->if_ioctl = rt2560_ioctl;
! 264: ifp->if_start = rt2560_start;
! 265: ifp->if_watchdog = rt2560_watchdog;
! 266: IFQ_SET_READY(&ifp->if_snd);
! 267: memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
! 268:
! 269: if_attach(ifp);
! 270: ieee80211_ifattach(ifp);
! 271: ic->ic_node_alloc = rt2560_node_alloc;
! 272: ic->ic_newassoc = rt2560_newassoc;
! 273: ic->ic_updateslot = rt2560_updateslot;
! 274:
! 275: /* override state transition machine */
! 276: sc->sc_newstate = ic->ic_newstate;
! 277: ic->ic_newstate = rt2560_newstate;
! 278: ieee80211_media_init(ifp, rt2560_media_change, ieee80211_media_status);
! 279:
! 280: #if NBPFILTER > 0
! 281: bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO,
! 282: sizeof (struct ieee80211_frame) + 64);
! 283:
! 284: sc->sc_rxtap_len = sizeof sc->sc_rxtapu;
! 285: sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
! 286: sc->sc_rxtap.wr_ihdr.it_present = htole32(RT2560_RX_RADIOTAP_PRESENT);
! 287:
! 288: sc->sc_txtap_len = sizeof sc->sc_txtapu;
! 289: sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
! 290: sc->sc_txtap.wt_ihdr.it_present = htole32(RT2560_TX_RADIOTAP_PRESENT);
! 291: #endif
! 292:
! 293: /*
! 294: * Make sure the interface is shutdown during reboot.
! 295: */
! 296: sc->sc_sdhook = shutdownhook_establish(rt2560_shutdown, sc);
! 297: if (sc->sc_sdhook == NULL) {
! 298: printf("%s: WARNING: unable to establish shutdown hook\n",
! 299: sc->sc_dev.dv_xname);
! 300: }
! 301: sc->sc_powerhook = powerhook_establish(rt2560_power, sc);
! 302: if (sc->sc_powerhook == NULL) {
! 303: printf("%s: WARNING: unable to establish power hook\n",
! 304: sc->sc_dev.dv_xname);
! 305: }
! 306: return 0;
! 307:
! 308: fail5: rt2560_free_tx_ring(sc, &sc->bcnq);
! 309: fail4: rt2560_free_tx_ring(sc, &sc->prioq);
! 310: fail3: rt2560_free_tx_ring(sc, &sc->atimq);
! 311: fail2: rt2560_free_tx_ring(sc, &sc->txq);
! 312: fail1: return ENXIO;
! 313: }
! 314:
! 315: int
! 316: rt2560_detach(void *xsc)
! 317: {
! 318: struct rt2560_softc *sc = xsc;
! 319: struct ifnet *ifp = &sc->sc_ic.ic_if;
! 320:
! 321: timeout_del(&sc->scan_to);
! 322: timeout_del(&sc->amrr_to);
! 323:
! 324: ieee80211_ifdetach(ifp); /* free all nodes */
! 325: if_detach(ifp);
! 326:
! 327: if (sc->sc_powerhook != NULL)
! 328: powerhook_disestablish(sc->sc_powerhook);
! 329: if (sc->sc_sdhook != NULL)
! 330: shutdownhook_disestablish(sc->sc_sdhook);
! 331:
! 332: rt2560_free_tx_ring(sc, &sc->txq);
! 333: rt2560_free_tx_ring(sc, &sc->atimq);
! 334: rt2560_free_tx_ring(sc, &sc->prioq);
! 335: rt2560_free_tx_ring(sc, &sc->bcnq);
! 336: rt2560_free_rx_ring(sc, &sc->rxq);
! 337:
! 338: return 0;
! 339: }
! 340:
! 341: int
! 342: rt2560_alloc_tx_ring(struct rt2560_softc *sc, struct rt2560_tx_ring *ring,
! 343: int count)
! 344: {
! 345: int i, nsegs, error;
! 346:
! 347: ring->count = count;
! 348: ring->queued = 0;
! 349: ring->cur = ring->next = 0;
! 350: ring->cur_encrypt = ring->next_encrypt = 0;
! 351:
! 352: error = bus_dmamap_create(sc->sc_dmat, count * RT2560_TX_DESC_SIZE, 1,
! 353: count * RT2560_TX_DESC_SIZE, 0, BUS_DMA_NOWAIT, &ring->map);
! 354: if (error != 0) {
! 355: printf("%s: could not create desc DMA map\n",
! 356: sc->sc_dev.dv_xname);
! 357: goto fail;
! 358: }
! 359:
! 360: error = bus_dmamem_alloc(sc->sc_dmat, count * RT2560_TX_DESC_SIZE,
! 361: PAGE_SIZE, 0, &ring->seg, 1, &nsegs, BUS_DMA_NOWAIT);
! 362: if (error != 0) {
! 363: printf("%s: could not allocate DMA memory\n",
! 364: sc->sc_dev.dv_xname);
! 365: goto fail;
! 366: }
! 367:
! 368: error = bus_dmamem_map(sc->sc_dmat, &ring->seg, nsegs,
! 369: count * RT2560_TX_DESC_SIZE, (caddr_t *)&ring->desc,
! 370: BUS_DMA_NOWAIT);
! 371: if (error != 0) {
! 372: printf("%s: could not map desc DMA memory\n",
! 373: sc->sc_dev.dv_xname);
! 374: goto fail;
! 375: }
! 376:
! 377: error = bus_dmamap_load(sc->sc_dmat, ring->map, ring->desc,
! 378: count * RT2560_TX_DESC_SIZE, NULL, BUS_DMA_NOWAIT);
! 379: if (error != 0) {
! 380: printf("%s: could not load desc DMA map\n",
! 381: sc->sc_dev.dv_xname);
! 382: goto fail;
! 383: }
! 384:
! 385: memset(ring->desc, 0, count * RT2560_TX_DESC_SIZE);
! 386: ring->physaddr = ring->map->dm_segs->ds_addr;
! 387:
! 388: ring->data = malloc(count * sizeof (struct rt2560_tx_data), M_DEVBUF,
! 389: M_NOWAIT);
! 390: if (ring->data == NULL) {
! 391: printf("%s: could not allocate soft data\n",
! 392: sc->sc_dev.dv_xname);
! 393: error = ENOMEM;
! 394: goto fail;
! 395: }
! 396:
! 397: memset(ring->data, 0, count * sizeof (struct rt2560_tx_data));
! 398: for (i = 0; i < count; i++) {
! 399: error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
! 400: RT2560_MAX_SCATTER, MCLBYTES, 0, BUS_DMA_NOWAIT,
! 401: &ring->data[i].map);
! 402: if (error != 0) {
! 403: printf("%s: could not create DMA map\n",
! 404: sc->sc_dev.dv_xname);
! 405: goto fail;
! 406: }
! 407: }
! 408:
! 409: return 0;
! 410:
! 411: fail: rt2560_free_tx_ring(sc, ring);
! 412: return error;
! 413: }
! 414:
! 415: void
! 416: rt2560_reset_tx_ring(struct rt2560_softc *sc, struct rt2560_tx_ring *ring)
! 417: {
! 418: int i;
! 419:
! 420: for (i = 0; i < ring->count; i++) {
! 421: struct rt2560_tx_desc *desc = &ring->desc[i];
! 422: struct rt2560_tx_data *data = &ring->data[i];
! 423:
! 424: if (data->m != NULL) {
! 425: bus_dmamap_sync(sc->sc_dmat, data->map, 0,
! 426: data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
! 427: bus_dmamap_unload(sc->sc_dmat, data->map);
! 428: m_freem(data->m);
! 429: data->m = NULL;
! 430: }
! 431:
! 432: /*
! 433: * The node has already been freed at that point so don't call
! 434: * ieee80211_release_node() here.
! 435: */
! 436: data->ni = NULL;
! 437:
! 438: desc->flags = 0;
! 439: }
! 440:
! 441: bus_dmamap_sync(sc->sc_dmat, ring->map, 0, ring->map->dm_mapsize,
! 442: BUS_DMASYNC_PREWRITE);
! 443:
! 444: ring->queued = 0;
! 445: ring->cur = ring->next = 0;
! 446: ring->cur_encrypt = ring->next_encrypt = 0;
! 447: }
! 448:
! 449: void
! 450: rt2560_free_tx_ring(struct rt2560_softc *sc, struct rt2560_tx_ring *ring)
! 451: {
! 452: int i;
! 453:
! 454: if (ring->desc != NULL) {
! 455: bus_dmamap_sync(sc->sc_dmat, ring->map, 0,
! 456: ring->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
! 457: bus_dmamap_unload(sc->sc_dmat, ring->map);
! 458: bus_dmamem_unmap(sc->sc_dmat, (caddr_t)ring->desc,
! 459: ring->count * RT2560_TX_DESC_SIZE);
! 460: bus_dmamem_free(sc->sc_dmat, &ring->seg, 1);
! 461: }
! 462:
! 463: if (ring->data != NULL) {
! 464: for (i = 0; i < ring->count; i++) {
! 465: struct rt2560_tx_data *data = &ring->data[i];
! 466:
! 467: if (data->m != NULL) {
! 468: bus_dmamap_sync(sc->sc_dmat, data->map, 0,
! 469: data->map->dm_mapsize,
! 470: BUS_DMASYNC_POSTWRITE);
! 471: bus_dmamap_unload(sc->sc_dmat, data->map);
! 472: m_freem(data->m);
! 473: }
! 474:
! 475: /*
! 476: * The node has already been freed at that point so
! 477: * don't call ieee80211_release_node() here.
! 478: */
! 479: data->ni = NULL;
! 480:
! 481: if (data->map != NULL)
! 482: bus_dmamap_destroy(sc->sc_dmat, data->map);
! 483: }
! 484: free(ring->data, M_DEVBUF);
! 485: }
! 486: }
! 487:
! 488: int
! 489: rt2560_alloc_rx_ring(struct rt2560_softc *sc, struct rt2560_rx_ring *ring,
! 490: int count)
! 491: {
! 492: int i, nsegs, error;
! 493:
! 494: ring->count = count;
! 495: ring->cur = ring->next = 0;
! 496: ring->cur_decrypt = 0;
! 497:
! 498: error = bus_dmamap_create(sc->sc_dmat, count * RT2560_RX_DESC_SIZE, 1,
! 499: count * RT2560_RX_DESC_SIZE, 0, BUS_DMA_NOWAIT, &ring->map);
! 500: if (error != 0) {
! 501: printf("%s: could not create desc DMA map\n",
! 502: sc->sc_dev.dv_xname);
! 503: goto fail;
! 504: }
! 505:
! 506: error = bus_dmamem_alloc(sc->sc_dmat, count * RT2560_RX_DESC_SIZE,
! 507: PAGE_SIZE, 0, &ring->seg, 1, &nsegs, BUS_DMA_NOWAIT);
! 508: if (error != 0) {
! 509: printf("%s: could not allocate DMA memory\n",
! 510: sc->sc_dev.dv_xname);
! 511: goto fail;
! 512: }
! 513:
! 514: error = bus_dmamem_map(sc->sc_dmat, &ring->seg, nsegs,
! 515: count * RT2560_RX_DESC_SIZE, (caddr_t *)&ring->desc,
! 516: BUS_DMA_NOWAIT);
! 517: if (error != 0) {
! 518: printf("%s: could not map desc DMA memory\n",
! 519: sc->sc_dev.dv_xname);
! 520: goto fail;
! 521: }
! 522:
! 523: error = bus_dmamap_load(sc->sc_dmat, ring->map, ring->desc,
! 524: count * RT2560_RX_DESC_SIZE, NULL, BUS_DMA_NOWAIT);
! 525: if (error != 0) {
! 526: printf("%s: could not load desc DMA map\n",
! 527: sc->sc_dev.dv_xname);
! 528: goto fail;
! 529: }
! 530:
! 531: memset(ring->desc, 0, count * RT2560_RX_DESC_SIZE);
! 532: ring->physaddr = ring->map->dm_segs->ds_addr;
! 533:
! 534: ring->data = malloc(count * sizeof (struct rt2560_rx_data), M_DEVBUF,
! 535: M_NOWAIT);
! 536: if (ring->data == NULL) {
! 537: printf("%s: could not allocate soft data\n",
! 538: sc->sc_dev.dv_xname);
! 539: error = ENOMEM;
! 540: goto fail;
! 541: }
! 542:
! 543: /*
! 544: * Pre-allocate Rx buffers and populate Rx ring.
! 545: */
! 546: memset(ring->data, 0, count * sizeof (struct rt2560_rx_data));
! 547: for (i = 0; i < count; i++) {
! 548: struct rt2560_rx_desc *desc = &sc->rxq.desc[i];
! 549: struct rt2560_rx_data *data = &sc->rxq.data[i];
! 550:
! 551: error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES,
! 552: 0, BUS_DMA_NOWAIT, &data->map);
! 553: if (error != 0) {
! 554: printf("%s: could not create DMA map\n",
! 555: sc->sc_dev.dv_xname);
! 556: goto fail;
! 557: }
! 558:
! 559: MGETHDR(data->m, M_DONTWAIT, MT_DATA);
! 560: if (data->m == NULL) {
! 561: printf("%s: could not allocate rx mbuf\n",
! 562: sc->sc_dev.dv_xname);
! 563: error = ENOMEM;
! 564: goto fail;
! 565: }
! 566: MCLGET(data->m, M_DONTWAIT);
! 567: if (!(data->m->m_flags & M_EXT)) {
! 568: printf("%s: could not allocate rx mbuf cluster\n",
! 569: sc->sc_dev.dv_xname);
! 570: error = ENOMEM;
! 571: goto fail;
! 572: }
! 573:
! 574: error = bus_dmamap_load(sc->sc_dmat, data->map,
! 575: mtod(data->m, void *), MCLBYTES, NULL, BUS_DMA_NOWAIT);
! 576: if (error != 0) {
! 577: printf("%s: could not load rx buf DMA map",
! 578: sc->sc_dev.dv_xname);
! 579: goto fail;
! 580: }
! 581:
! 582: desc->flags = htole32(RT2560_RX_BUSY);
! 583: desc->physaddr = htole32(data->map->dm_segs->ds_addr);
! 584: }
! 585:
! 586: bus_dmamap_sync(sc->sc_dmat, ring->map, 0, ring->map->dm_mapsize,
! 587: BUS_DMASYNC_PREWRITE);
! 588:
! 589: return 0;
! 590:
! 591: fail: rt2560_free_rx_ring(sc, ring);
! 592: return error;
! 593: }
! 594:
! 595: void
! 596: rt2560_reset_rx_ring(struct rt2560_softc *sc, struct rt2560_rx_ring *ring)
! 597: {
! 598: int i;
! 599:
! 600: for (i = 0; i < ring->count; i++) {
! 601: ring->desc[i].flags = htole32(RT2560_RX_BUSY);
! 602: ring->data[i].drop = 0;
! 603: }
! 604:
! 605: bus_dmamap_sync(sc->sc_dmat, ring->map, 0, ring->map->dm_mapsize,
! 606: BUS_DMASYNC_PREWRITE);
! 607:
! 608: ring->cur = ring->next = 0;
! 609: ring->cur_decrypt = 0;
! 610: }
! 611:
! 612: void
! 613: rt2560_free_rx_ring(struct rt2560_softc *sc, struct rt2560_rx_ring *ring)
! 614: {
! 615: int i;
! 616:
! 617: if (ring->desc != NULL) {
! 618: bus_dmamap_sync(sc->sc_dmat, ring->map, 0,
! 619: ring->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
! 620: bus_dmamap_unload(sc->sc_dmat, ring->map);
! 621: bus_dmamem_unmap(sc->sc_dmat, (caddr_t)ring->desc,
! 622: ring->count * RT2560_RX_DESC_SIZE);
! 623: bus_dmamem_free(sc->sc_dmat, &ring->seg, 1);
! 624: }
! 625:
! 626: if (ring->data != NULL) {
! 627: for (i = 0; i < ring->count; i++) {
! 628: struct rt2560_rx_data *data = &ring->data[i];
! 629:
! 630: if (data->m != NULL) {
! 631: bus_dmamap_sync(sc->sc_dmat, data->map, 0,
! 632: data->map->dm_mapsize,
! 633: BUS_DMASYNC_POSTREAD);
! 634: bus_dmamap_unload(sc->sc_dmat, data->map);
! 635: m_freem(data->m);
! 636: }
! 637:
! 638: if (data->map != NULL)
! 639: bus_dmamap_destroy(sc->sc_dmat, data->map);
! 640: }
! 641: free(ring->data, M_DEVBUF);
! 642: }
! 643: }
! 644:
! 645: struct ieee80211_node *
! 646: rt2560_node_alloc(struct ieee80211com *ic)
! 647: {
! 648: struct rt2560_node *rn;
! 649:
! 650: rn = malloc(sizeof (struct rt2560_node), M_DEVBUF, M_NOWAIT);
! 651: if (rn != NULL)
! 652: bzero(rn, sizeof (struct rt2560_node));
! 653: return (struct ieee80211_node *)rn;
! 654: }
! 655:
! 656: int
! 657: rt2560_media_change(struct ifnet *ifp)
! 658: {
! 659: int error;
! 660:
! 661: error = ieee80211_media_change(ifp);
! 662: if (error != ENETRESET)
! 663: return error;
! 664:
! 665: if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING))
! 666: rt2560_init(ifp);
! 667:
! 668: return 0;
! 669: }
! 670:
! 671: /*
! 672: * This function is called periodically (every 200ms) during scanning to
! 673: * switch from one channel to another.
! 674: */
! 675: void
! 676: rt2560_next_scan(void *arg)
! 677: {
! 678: struct rt2560_softc *sc = arg;
! 679: struct ieee80211com *ic = &sc->sc_ic;
! 680: struct ifnet *ifp = &ic->ic_if;
! 681: int s;
! 682:
! 683: s = splnet();
! 684: if (ic->ic_state == IEEE80211_S_SCAN)
! 685: ieee80211_next_scan(ifp);
! 686: splx(s);
! 687: }
! 688:
! 689: /*
! 690: * This function is called for each neighbor node.
! 691: */
! 692: void
! 693: rt2560_iter_func(void *arg, struct ieee80211_node *ni)
! 694: {
! 695: struct rt2560_softc *sc = arg;
! 696: struct rt2560_node *rn = (struct rt2560_node *)ni;
! 697:
! 698: ieee80211_amrr_choose(&sc->amrr, ni, &rn->amn);
! 699: }
! 700:
! 701: void
! 702: rt2560_amrr_timeout(void *arg)
! 703: {
! 704: struct rt2560_softc *sc = arg;
! 705: struct ieee80211com *ic = &sc->sc_ic;
! 706: int s;
! 707:
! 708: s = splnet();
! 709: if (ic->ic_opmode == IEEE80211_M_STA)
! 710: rt2560_iter_func(sc, ic->ic_bss);
! 711: else
! 712: ieee80211_iterate_nodes(ic, rt2560_iter_func, sc);
! 713: splx(s);
! 714:
! 715: timeout_add(&sc->amrr_to, hz / 2);
! 716: }
! 717:
! 718: void
! 719: rt2560_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
! 720: {
! 721: struct rt2560_softc *sc = ic->ic_softc;
! 722: int i;
! 723:
! 724: ieee80211_amrr_node_init(&sc->amrr, &((struct rt2560_node *)ni)->amn);
! 725:
! 726: /* set rate to some reasonable initial value */
! 727: for (i = ni->ni_rates.rs_nrates - 1;
! 728: i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL) > 72;
! 729: i--);
! 730: ni->ni_txrate = i;
! 731: }
! 732:
! 733: int
! 734: rt2560_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
! 735: {
! 736: struct rt2560_softc *sc = ic->ic_if.if_softc;
! 737: enum ieee80211_state ostate;
! 738: struct ieee80211_node *ni;
! 739: struct mbuf *m;
! 740: int error = 0;
! 741:
! 742: ostate = ic->ic_state;
! 743: timeout_del(&sc->scan_to);
! 744: timeout_del(&sc->amrr_to);
! 745:
! 746: switch (nstate) {
! 747: case IEEE80211_S_INIT:
! 748: if (ostate == IEEE80211_S_RUN) {
! 749: /* abort TSF synchronization */
! 750: RAL_WRITE(sc, RT2560_CSR14, 0);
! 751:
! 752: /* turn association led off */
! 753: rt2560_update_led(sc, 0, 0);
! 754: }
! 755: break;
! 756:
! 757: case IEEE80211_S_SCAN:
! 758: rt2560_set_chan(sc, ic->ic_bss->ni_chan);
! 759: timeout_add(&sc->scan_to, hz / 5);
! 760: break;
! 761:
! 762: case IEEE80211_S_AUTH:
! 763: rt2560_set_chan(sc, ic->ic_bss->ni_chan);
! 764: break;
! 765:
! 766: case IEEE80211_S_ASSOC:
! 767: rt2560_set_chan(sc, ic->ic_bss->ni_chan);
! 768: break;
! 769:
! 770: case IEEE80211_S_RUN:
! 771: rt2560_set_chan(sc, ic->ic_bss->ni_chan);
! 772:
! 773: ni = ic->ic_bss;
! 774:
! 775: if (ic->ic_opmode != IEEE80211_M_MONITOR) {
! 776: rt2560_update_plcp(sc);
! 777: rt2560_set_slottime(sc);
! 778: rt2560_set_basicrates(sc);
! 779: rt2560_set_bssid(sc, ni->ni_bssid);
! 780: }
! 781:
! 782: if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
! 783: ic->ic_opmode == IEEE80211_M_IBSS) {
! 784: m = ieee80211_beacon_alloc(ic, ni);
! 785: if (m == NULL) {
! 786: printf("%s: could not allocate beacon\n",
! 787: sc->sc_dev.dv_xname);
! 788: error = ENOBUFS;
! 789: break;
! 790: }
! 791:
! 792: error = rt2560_tx_bcn(sc, m, ni);
! 793: if (error != 0)
! 794: break;
! 795: }
! 796:
! 797: /* turn assocation led on */
! 798: rt2560_update_led(sc, 1, 0);
! 799:
! 800: if (ic->ic_opmode == IEEE80211_M_STA) {
! 801: /* fake a join to init the tx rate */
! 802: rt2560_newassoc(ic, ni, 1);
! 803: }
! 804:
! 805: if (ic->ic_opmode != IEEE80211_M_MONITOR) {
! 806: /* start automatic rate control timer */
! 807: if (ic->ic_fixed_rate == -1)
! 808: timeout_add(&sc->amrr_to, hz / 2);
! 809:
! 810: rt2560_enable_tsf_sync(sc);
! 811: }
! 812: break;
! 813: }
! 814:
! 815: return (error != 0) ? error : sc->sc_newstate(ic, nstate, arg);
! 816: }
! 817:
! 818: /*
! 819: * Read 16 bits at address 'addr' from the serial EEPROM (either 93C46 or
! 820: * 93C66).
! 821: */
! 822: uint16_t
! 823: rt2560_eeprom_read(struct rt2560_softc *sc, uint8_t addr)
! 824: {
! 825: uint32_t tmp;
! 826: uint16_t val;
! 827: int n;
! 828:
! 829: /* clock C once before the first command */
! 830: RT2560_EEPROM_CTL(sc, 0);
! 831:
! 832: RT2560_EEPROM_CTL(sc, RT2560_S);
! 833: RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_C);
! 834: RT2560_EEPROM_CTL(sc, RT2560_S);
! 835:
! 836: /* write start bit (1) */
! 837: RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_D);
! 838: RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_D | RT2560_C);
! 839:
! 840: /* write READ opcode (10) */
! 841: RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_D);
! 842: RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_D | RT2560_C);
! 843: RT2560_EEPROM_CTL(sc, RT2560_S);
! 844: RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_C);
! 845:
! 846: /* write address (A5-A0 or A7-A0) */
! 847: n = (RAL_READ(sc, RT2560_CSR21) & RT2560_93C46) ? 5 : 7;
! 848: for (; n >= 0; n--) {
! 849: RT2560_EEPROM_CTL(sc, RT2560_S |
! 850: (((addr >> n) & 1) << RT2560_SHIFT_D));
! 851: RT2560_EEPROM_CTL(sc, RT2560_S |
! 852: (((addr >> n) & 1) << RT2560_SHIFT_D) | RT2560_C);
! 853: }
! 854:
! 855: RT2560_EEPROM_CTL(sc, RT2560_S);
! 856:
! 857: /* read data Q15-Q0 */
! 858: val = 0;
! 859: for (n = 15; n >= 0; n--) {
! 860: RT2560_EEPROM_CTL(sc, RT2560_S | RT2560_C);
! 861: tmp = RAL_READ(sc, RT2560_CSR21);
! 862: val |= ((tmp & RT2560_Q) >> RT2560_SHIFT_Q) << n;
! 863: RT2560_EEPROM_CTL(sc, RT2560_S);
! 864: }
! 865:
! 866: RT2560_EEPROM_CTL(sc, 0);
! 867:
! 868: /* clear Chip Select and clock C */
! 869: RT2560_EEPROM_CTL(sc, RT2560_S);
! 870: RT2560_EEPROM_CTL(sc, 0);
! 871: RT2560_EEPROM_CTL(sc, RT2560_C);
! 872:
! 873: return val;
! 874: }
! 875:
! 876: /*
! 877: * Some frames were processed by the hardware cipher engine and are ready for
! 878: * transmission.
! 879: */
! 880: void
! 881: rt2560_encryption_intr(struct rt2560_softc *sc)
! 882: {
! 883: int hw;
! 884:
! 885: /* retrieve last descriptor index processed by cipher engine */
! 886: hw = (RAL_READ(sc, RT2560_SECCSR1) - sc->txq.physaddr) /
! 887: RT2560_TX_DESC_SIZE;
! 888:
! 889: for (; sc->txq.next_encrypt != hw;) {
! 890: struct rt2560_tx_desc *desc =
! 891: &sc->txq.desc[sc->txq.next_encrypt];
! 892:
! 893: bus_dmamap_sync(sc->sc_dmat, sc->txq.map,
! 894: sc->txq.next_encrypt * RT2560_TX_DESC_SIZE,
! 895: RT2560_TX_DESC_SIZE, BUS_DMASYNC_POSTREAD);
! 896:
! 897: if (letoh32(desc->flags) &
! 898: (RT2560_TX_BUSY | RT2560_TX_CIPHER_BUSY))
! 899: break;
! 900:
! 901: /* for TKIP, swap eiv field to fix a bug in ASIC */
! 902: if ((letoh32(desc->flags) & RT2560_TX_CIPHER_MASK) ==
! 903: RT2560_TX_CIPHER_TKIP)
! 904: desc->eiv = swap32(desc->eiv);
! 905:
! 906: /* mark the frame ready for transmission */
! 907: desc->flags |= htole32(RT2560_TX_BUSY | RT2560_TX_VALID);
! 908:
! 909: bus_dmamap_sync(sc->sc_dmat, sc->txq.map,
! 910: sc->txq.next_encrypt * RT2560_TX_DESC_SIZE,
! 911: RT2560_TX_DESC_SIZE, BUS_DMASYNC_PREWRITE);
! 912:
! 913: DPRINTFN(15, ("encryption done idx=%u\n",
! 914: sc->txq.next_encrypt));
! 915:
! 916: sc->txq.next_encrypt =
! 917: (sc->txq.next_encrypt + 1) % RT2560_TX_RING_COUNT;
! 918: }
! 919:
! 920: /* kick Tx */
! 921: RAL_WRITE(sc, RT2560_TXCSR0, RT2560_KICK_TX);
! 922: }
! 923:
! 924: void
! 925: rt2560_tx_intr(struct rt2560_softc *sc)
! 926: {
! 927: struct ieee80211com *ic = &sc->sc_ic;
! 928: struct ifnet *ifp = &ic->ic_if;
! 929:
! 930: for (;;) {
! 931: struct rt2560_tx_desc *desc = &sc->txq.desc[sc->txq.next];
! 932: struct rt2560_tx_data *data = &sc->txq.data[sc->txq.next];
! 933: struct rt2560_node *rn;
! 934:
! 935: bus_dmamap_sync(sc->sc_dmat, sc->txq.map,
! 936: sc->txq.next * RT2560_TX_DESC_SIZE, RT2560_TX_DESC_SIZE,
! 937: BUS_DMASYNC_POSTREAD);
! 938:
! 939: if ((letoh32(desc->flags) & RT2560_TX_BUSY) ||
! 940: (letoh32(desc->flags) & RT2560_TX_CIPHER_BUSY) ||
! 941: !(letoh32(desc->flags) & RT2560_TX_VALID))
! 942: break;
! 943:
! 944: rn = (struct rt2560_node *)data->ni;
! 945:
! 946: switch (letoh32(desc->flags) & RT2560_TX_RESULT_MASK) {
! 947: case RT2560_TX_SUCCESS:
! 948: DPRINTFN(10, ("data frame sent successfully\n"));
! 949: rn->amn.amn_txcnt++;
! 950: ifp->if_opackets++;
! 951: break;
! 952:
! 953: case RT2560_TX_SUCCESS_RETRY:
! 954: DPRINTFN(9, ("data frame sent after %u retries\n",
! 955: (letoh32(desc->flags) >> 5) & 0x7));
! 956: rn->amn.amn_txcnt++;
! 957: rn->amn.amn_retrycnt++;
! 958: ifp->if_opackets++;
! 959: break;
! 960:
! 961: case RT2560_TX_FAIL_RETRY:
! 962: DPRINTFN(9, ("sending data frame failed (too much "
! 963: "retries)\n"));
! 964: rn->amn.amn_txcnt++;
! 965: rn->amn.amn_retrycnt++;
! 966: ifp->if_oerrors++;
! 967: break;
! 968:
! 969: case RT2560_TX_FAIL_INVALID:
! 970: case RT2560_TX_FAIL_OTHER:
! 971: default:
! 972: printf("%s: sending data frame failed 0x%08x\n",
! 973: sc->sc_dev.dv_xname, letoh32(desc->flags));
! 974: ifp->if_oerrors++;
! 975: }
! 976:
! 977: bus_dmamap_sync(sc->sc_dmat, data->map, 0,
! 978: data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
! 979: bus_dmamap_unload(sc->sc_dmat, data->map);
! 980: m_freem(data->m);
! 981: data->m = NULL;
! 982: ieee80211_release_node(ic, data->ni);
! 983: data->ni = NULL;
! 984:
! 985: /* descriptor is no longer valid */
! 986: desc->flags &= ~htole32(RT2560_TX_VALID);
! 987:
! 988: bus_dmamap_sync(sc->sc_dmat, sc->txq.map,
! 989: sc->txq.next * RT2560_TX_DESC_SIZE, RT2560_TX_DESC_SIZE,
! 990: BUS_DMASYNC_PREWRITE);
! 991:
! 992: DPRINTFN(15, ("tx done idx=%u\n", sc->txq.next));
! 993:
! 994: sc->txq.queued--;
! 995: sc->txq.next = (sc->txq.next + 1) % RT2560_TX_RING_COUNT;
! 996: }
! 997:
! 998: sc->sc_tx_timer = 0;
! 999: ifp->if_flags &= ~IFF_OACTIVE;
! 1000: rt2560_start(ifp);
! 1001: }
! 1002:
! 1003: void
! 1004: rt2560_prio_intr(struct rt2560_softc *sc)
! 1005: {
! 1006: struct ieee80211com *ic = &sc->sc_ic;
! 1007: struct ifnet *ifp = &ic->ic_if;
! 1008:
! 1009: for (;;) {
! 1010: struct rt2560_tx_desc *desc = &sc->prioq.desc[sc->prioq.next];
! 1011: struct rt2560_tx_data *data = &sc->prioq.data[sc->prioq.next];
! 1012:
! 1013: bus_dmamap_sync(sc->sc_dmat, sc->prioq.map,
! 1014: sc->prioq.next * RT2560_TX_DESC_SIZE, RT2560_TX_DESC_SIZE,
! 1015: BUS_DMASYNC_POSTREAD);
! 1016:
! 1017: if ((letoh32(desc->flags) & RT2560_TX_BUSY) ||
! 1018: !(letoh32(desc->flags) & RT2560_TX_VALID))
! 1019: break;
! 1020:
! 1021: switch (letoh32(desc->flags) & RT2560_TX_RESULT_MASK) {
! 1022: case RT2560_TX_SUCCESS:
! 1023: DPRINTFN(10, ("mgt frame sent successfully\n"));
! 1024: break;
! 1025:
! 1026: case RT2560_TX_SUCCESS_RETRY:
! 1027: DPRINTFN(9, ("mgt frame sent after %u retries\n",
! 1028: (letoh32(desc->flags) >> 5) & 0x7));
! 1029: break;
! 1030:
! 1031: case RT2560_TX_FAIL_RETRY:
! 1032: DPRINTFN(9, ("sending mgt frame failed (too much "
! 1033: "retries)\n"));
! 1034: break;
! 1035:
! 1036: case RT2560_TX_FAIL_INVALID:
! 1037: case RT2560_TX_FAIL_OTHER:
! 1038: default:
! 1039: printf("%s: sending mgt frame failed 0x%08x\n",
! 1040: sc->sc_dev.dv_xname, letoh32(desc->flags));
! 1041: }
! 1042:
! 1043: bus_dmamap_sync(sc->sc_dmat, data->map, 0,
! 1044: data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
! 1045: bus_dmamap_unload(sc->sc_dmat, data->map);
! 1046: m_freem(data->m);
! 1047: data->m = NULL;
! 1048: ieee80211_release_node(ic, data->ni);
! 1049: data->ni = NULL;
! 1050:
! 1051: /* descriptor is no longer valid */
! 1052: desc->flags &= ~htole32(RT2560_TX_VALID);
! 1053:
! 1054: bus_dmamap_sync(sc->sc_dmat, sc->prioq.map,
! 1055: sc->prioq.next * RT2560_TX_DESC_SIZE, RT2560_TX_DESC_SIZE,
! 1056: BUS_DMASYNC_PREWRITE);
! 1057:
! 1058: DPRINTFN(15, ("prio done idx=%u\n", sc->prioq.next));
! 1059:
! 1060: sc->prioq.queued--;
! 1061: sc->prioq.next = (sc->prioq.next + 1) % RT2560_PRIO_RING_COUNT;
! 1062: }
! 1063:
! 1064: sc->sc_tx_timer = 0;
! 1065: ifp->if_flags &= ~IFF_OACTIVE;
! 1066: rt2560_start(ifp);
! 1067: }
! 1068:
! 1069: /*
! 1070: * Some frames were processed by the hardware cipher engine and are ready for
! 1071: * transmission to the IEEE802.11 layer.
! 1072: */
! 1073: void
! 1074: rt2560_decryption_intr(struct rt2560_softc *sc)
! 1075: {
! 1076: struct ieee80211com *ic = &sc->sc_ic;
! 1077: struct ifnet *ifp = &ic->ic_if;
! 1078: struct ieee80211_frame *wh;
! 1079: struct ieee80211_node *ni;
! 1080: struct mbuf *mnew, *m;
! 1081: int hw, error;
! 1082:
! 1083: /* retrieve last decriptor index processed by cipher engine */
! 1084: hw = (RAL_READ(sc, RT2560_SECCSR0) - sc->rxq.physaddr) /
! 1085: RT2560_RX_DESC_SIZE;
! 1086:
! 1087: for (; sc->rxq.cur_decrypt != hw;) {
! 1088: struct rt2560_rx_desc *desc =
! 1089: &sc->rxq.desc[sc->rxq.cur_decrypt];
! 1090: struct rt2560_rx_data *data =
! 1091: &sc->rxq.data[sc->rxq.cur_decrypt];
! 1092:
! 1093: bus_dmamap_sync(sc->sc_dmat, sc->rxq.map,
! 1094: sc->rxq.cur_decrypt * RT2560_TX_DESC_SIZE,
! 1095: RT2560_TX_DESC_SIZE, BUS_DMASYNC_POSTREAD);
! 1096:
! 1097: if (letoh32(desc->flags) &
! 1098: (RT2560_RX_BUSY | RT2560_RX_CIPHER_BUSY))
! 1099: break;
! 1100:
! 1101: if (data->drop) {
! 1102: ifp->if_ierrors++;
! 1103: goto skip;
! 1104: }
! 1105:
! 1106: if ((letoh32(desc->flags) & RT2560_RX_CIPHER_MASK) != 0 &&
! 1107: (letoh32(desc->flags) & RT2560_RX_ICV_ERROR)) {
! 1108: ifp->if_ierrors++;
! 1109: goto skip;
! 1110: }
! 1111:
! 1112: /*
! 1113: * Try to allocate a new mbuf for this ring element and load it
! 1114: * before processing the current mbuf. If the ring element
! 1115: * cannot be loaded, drop the received packet and reuse the old
! 1116: * mbuf. In the unlikely case that the old mbuf can't be
! 1117: * reloaded either, explicitly panic.
! 1118: */
! 1119: MGETHDR(mnew, M_DONTWAIT, MT_DATA);
! 1120: if (mnew == NULL) {
! 1121: ifp->if_ierrors++;
! 1122: goto skip;
! 1123: }
! 1124: MCLGET(mnew, M_DONTWAIT);
! 1125: if (!(mnew->m_flags & M_EXT)) {
! 1126: m_freem(mnew);
! 1127: ifp->if_ierrors++;
! 1128: goto skip;
! 1129: }
! 1130:
! 1131: bus_dmamap_sync(sc->sc_dmat, data->map, 0,
! 1132: data->map->dm_mapsize, BUS_DMASYNC_POSTREAD);
! 1133: bus_dmamap_unload(sc->sc_dmat, data->map);
! 1134:
! 1135: error = bus_dmamap_load(sc->sc_dmat, data->map,
! 1136: mtod(mnew, void *), MCLBYTES, NULL, BUS_DMA_NOWAIT);
! 1137: if (error != 0) {
! 1138: m_freem(mnew);
! 1139:
! 1140: /* try to reload the old mbuf */
! 1141: error = bus_dmamap_load(sc->sc_dmat, data->map,
! 1142: mtod(data->m, void *), MCLBYTES, NULL,
! 1143: BUS_DMA_NOWAIT);
! 1144: if (error != 0) {
! 1145: /* very unlikely that it will fail... */
! 1146: panic("%s: could not load old rx mbuf",
! 1147: sc->sc_dev.dv_xname);
! 1148: }
! 1149: ifp->if_ierrors++;
! 1150: goto skip;
! 1151: }
! 1152:
! 1153: /*
! 1154: * New mbuf successfully loaded, update Rx ring and continue
! 1155: * processing.
! 1156: */
! 1157: m = data->m;
! 1158: data->m = mnew;
! 1159: desc->physaddr = htole32(data->map->dm_segs->ds_addr);
! 1160:
! 1161: /* finalize mbuf */
! 1162: m->m_pkthdr.rcvif = ifp;
! 1163: m->m_pkthdr.len = m->m_len =
! 1164: (letoh32(desc->flags) >> 16) & 0xfff;
! 1165:
! 1166: #if NBPFILTER > 0
! 1167: if (sc->sc_drvbpf != NULL) {
! 1168: struct mbuf mb;
! 1169: struct rt2560_rx_radiotap_header *tap = &sc->sc_rxtap;
! 1170: uint32_t tsf_lo, tsf_hi;
! 1171:
! 1172: /* get timestamp (low and high 32 bits) */
! 1173: tsf_hi = RAL_READ(sc, RT2560_CSR17);
! 1174: tsf_lo = RAL_READ(sc, RT2560_CSR16);
! 1175:
! 1176: tap->wr_tsf =
! 1177: htole64(((uint64_t)tsf_hi << 32) | tsf_lo);
! 1178: tap->wr_flags = 0;
! 1179: tap->wr_rate = rt2560_rxrate(desc);
! 1180: tap->wr_chan_freq = htole16(ic->ic_ibss_chan->ic_freq);
! 1181: tap->wr_chan_flags =
! 1182: htole16(ic->ic_ibss_chan->ic_flags);
! 1183: tap->wr_antenna = sc->rx_ant;
! 1184: tap->wr_antsignal = desc->rssi;
! 1185:
! 1186: mb.m_data = (caddr_t)tap;
! 1187: mb.m_len = sc->sc_txtap_len;
! 1188: mb.m_next = m;
! 1189: mb.m_nextpkt = NULL;
! 1190: mb.m_type = 0;
! 1191: mb.m_flags = 0;
! 1192: bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN);
! 1193: }
! 1194: #endif
! 1195: wh = mtod(m, struct ieee80211_frame *);
! 1196: ni = ieee80211_find_rxnode(ic, wh);
! 1197:
! 1198: /* send the frame to the 802.11 layer */
! 1199: ieee80211_input(ifp, m, ni, desc->rssi, 0);
! 1200:
! 1201: /* node is no longer needed */
! 1202: ieee80211_release_node(ic, ni);
! 1203:
! 1204: skip: desc->flags = htole32(RT2560_RX_BUSY);
! 1205:
! 1206: bus_dmamap_sync(sc->sc_dmat, sc->rxq.map,
! 1207: sc->rxq.cur_decrypt * RT2560_TX_DESC_SIZE,
! 1208: RT2560_TX_DESC_SIZE, BUS_DMASYNC_PREWRITE);
! 1209:
! 1210: DPRINTFN(15, ("decryption done idx=%u\n", sc->rxq.cur_decrypt));
! 1211:
! 1212: sc->rxq.cur_decrypt =
! 1213: (sc->rxq.cur_decrypt + 1) % RT2560_RX_RING_COUNT;
! 1214: }
! 1215:
! 1216: /*
! 1217: * In HostAP mode, ieee80211_input() will enqueue packets in if_snd
! 1218: * without calling if_start().
! 1219: */
! 1220: if (!IFQ_IS_EMPTY(&ifp->if_snd) && !(ifp->if_flags & IFF_OACTIVE))
! 1221: rt2560_start(ifp);
! 1222: }
! 1223:
! 1224: /*
! 1225: * Some frames were received. Pass them to the hardware cipher engine before
! 1226: * sending them to the 802.11 layer.
! 1227: */
! 1228: void
! 1229: rt2560_rx_intr(struct rt2560_softc *sc)
! 1230: {
! 1231: for (;;) {
! 1232: struct rt2560_rx_desc *desc = &sc->rxq.desc[sc->rxq.cur];
! 1233: struct rt2560_rx_data *data = &sc->rxq.data[sc->rxq.cur];
! 1234:
! 1235: bus_dmamap_sync(sc->sc_dmat, sc->rxq.map,
! 1236: sc->rxq.cur * RT2560_RX_DESC_SIZE, RT2560_RX_DESC_SIZE,
! 1237: BUS_DMASYNC_POSTREAD);
! 1238:
! 1239: if (letoh32(desc->flags) &
! 1240: (RT2560_RX_BUSY | RT2560_RX_CIPHER_BUSY))
! 1241: break;
! 1242:
! 1243: data->drop = 0;
! 1244:
! 1245: if (letoh32(desc->flags) &
! 1246: (RT2560_RX_PHY_ERROR | RT2560_RX_CRC_ERROR)) {
! 1247: /*
! 1248: * This should not happen since we did not request
! 1249: * to receive those frames when we filled RXCSR0.
! 1250: */
! 1251: DPRINTFN(5, ("PHY or CRC error flags 0x%08x\n",
! 1252: letoh32(desc->flags)));
! 1253: data->drop = 1;
! 1254: }
! 1255:
! 1256: if (((letoh32(desc->flags) >> 16) & 0xfff) > MCLBYTES) {
! 1257: DPRINTFN(5, ("bad length\n"));
! 1258: data->drop = 1;
! 1259: }
! 1260:
! 1261: /* mark the frame for decryption */
! 1262: desc->flags |= htole32(RT2560_RX_CIPHER_BUSY);
! 1263:
! 1264: bus_dmamap_sync(sc->sc_dmat, sc->rxq.map,
! 1265: sc->rxq.cur * RT2560_RX_DESC_SIZE, RT2560_RX_DESC_SIZE,
! 1266: BUS_DMASYNC_PREWRITE);
! 1267:
! 1268: DPRINTFN(15, ("rx done idx=%u\n", sc->rxq.cur));
! 1269:
! 1270: sc->rxq.cur = (sc->rxq.cur + 1) % RT2560_RX_RING_COUNT;
! 1271: }
! 1272:
! 1273: /* kick decrypt */
! 1274: RAL_WRITE(sc, RT2560_SECCSR0, RT2560_KICK_DECRYPT);
! 1275: }
! 1276:
! 1277: /*
! 1278: * This function is called in HostAP or IBSS modes when it's time to send a
! 1279: * new beacon (every ni_intval milliseconds).
! 1280: */
! 1281: void
! 1282: rt2560_beacon_expire(struct rt2560_softc *sc)
! 1283: {
! 1284: struct ieee80211com *ic = &sc->sc_ic;
! 1285: struct rt2560_tx_data *data;
! 1286:
! 1287: if (ic->ic_opmode != IEEE80211_M_IBSS &&
! 1288: ic->ic_opmode != IEEE80211_M_HOSTAP)
! 1289: return;
! 1290:
! 1291: data = &sc->bcnq.data[sc->bcnq.next];
! 1292:
! 1293: if (sc->sc_flags & RT2560_UPDATE_SLOT) {
! 1294: sc->sc_flags &= ~RT2560_UPDATE_SLOT;
! 1295: sc->sc_flags |= RT2560_SET_SLOTTIME;
! 1296: } else if (sc->sc_flags & RT2560_SET_SLOTTIME) {
! 1297: sc->sc_flags &= ~RT2560_SET_SLOTTIME;
! 1298: rt2560_set_slottime(sc);
! 1299: }
! 1300:
! 1301: if (ic->ic_curmode == IEEE80211_MODE_11G) {
! 1302: /* update ERP Information Element */
! 1303: *sc->erp = ic->ic_bss->ni_erp;
! 1304: bus_dmamap_sync(sc->sc_dmat, data->map, 0,
! 1305: data->map->dm_mapsize, BUS_DMASYNC_PREWRITE);
! 1306: }
! 1307:
! 1308: #if defined(RT2560_DEBUG) && NBPFILTER > 0
! 1309: if (ic->ic_rawbpf != NULL)
! 1310: bpf_mtap(ic->ic_rawbpf, data->m, BPF_DIRECTION_OUT);
! 1311: #endif
! 1312:
! 1313: DPRINTFN(15, ("beacon expired\n"));
! 1314: }
! 1315:
! 1316: void
! 1317: rt2560_wakeup_expire(struct rt2560_softc *sc)
! 1318: {
! 1319: DPRINTFN(15, ("wakeup expired\n"));
! 1320: }
! 1321:
! 1322: int
! 1323: rt2560_intr(void *arg)
! 1324: {
! 1325: struct rt2560_softc *sc = arg;
! 1326: struct ifnet *ifp = &sc->sc_ic.ic_if;
! 1327: uint32_t r;
! 1328:
! 1329: if ((r = RAL_READ(sc, RT2560_CSR7)) == 0)
! 1330: return 0; /* not for us */
! 1331:
! 1332: /* disable interrupts */
! 1333: RAL_WRITE(sc, RT2560_CSR8, 0xffffffff);
! 1334:
! 1335: /* acknowledge interrupts */
! 1336: RAL_WRITE(sc, RT2560_CSR7, r);
! 1337:
! 1338: /* don't re-enable interrupts if we're shutting down */
! 1339: if (!(ifp->if_flags & IFF_RUNNING))
! 1340: return 0;
! 1341:
! 1342: if (r & RT2560_BEACON_EXPIRE)
! 1343: rt2560_beacon_expire(sc);
! 1344:
! 1345: if (r & RT2560_WAKEUP_EXPIRE)
! 1346: rt2560_wakeup_expire(sc);
! 1347:
! 1348: if (r & RT2560_ENCRYPTION_DONE)
! 1349: rt2560_encryption_intr(sc);
! 1350:
! 1351: if (r & RT2560_TX_DONE)
! 1352: rt2560_tx_intr(sc);
! 1353:
! 1354: if (r & RT2560_PRIO_DONE)
! 1355: rt2560_prio_intr(sc);
! 1356:
! 1357: if (r & RT2560_DECRYPTION_DONE)
! 1358: rt2560_decryption_intr(sc);
! 1359:
! 1360: if (r & RT2560_RX_DONE)
! 1361: rt2560_rx_intr(sc);
! 1362:
! 1363: /* re-enable interrupts */
! 1364: RAL_WRITE(sc, RT2560_CSR8, RT2560_INTR_MASK);
! 1365:
! 1366: return 1;
! 1367: }
! 1368:
! 1369: /* quickly determine if a given rate is CCK or OFDM */
! 1370: #define RAL_RATE_IS_OFDM(rate) ((rate) >= 12 && (rate) != 22)
! 1371:
! 1372: #define RAL_ACK_SIZE 14 /* 10 + 4(FCS) */
! 1373: #define RAL_CTS_SIZE 14 /* 10 + 4(FCS) */
! 1374:
! 1375: #define RAL_SIFS 10 /* us */
! 1376:
! 1377: #define RT2560_RXTX_TURNAROUND 10 /* us */
! 1378:
! 1379: /*
! 1380: * This function is only used by the Rx radiotap code. It returns the rate at
! 1381: * which a given frame was received.
! 1382: */
! 1383: #if NBPFILTER > 0
! 1384: uint8_t
! 1385: rt2560_rxrate(const struct rt2560_rx_desc *desc)
! 1386: {
! 1387: if (letoh32(desc->flags) & RT2560_RX_OFDM) {
! 1388: /* reverse function of rt2560_plcp_signal */
! 1389: switch (desc->rate) {
! 1390: case 0xb: return 12;
! 1391: case 0xf: return 18;
! 1392: case 0xa: return 24;
! 1393: case 0xe: return 36;
! 1394: case 0x9: return 48;
! 1395: case 0xd: return 72;
! 1396: case 0x8: return 96;
! 1397: case 0xc: return 108;
! 1398: }
! 1399: } else {
! 1400: if (desc->rate == 10)
! 1401: return 2;
! 1402: if (desc->rate == 20)
! 1403: return 4;
! 1404: if (desc->rate == 55)
! 1405: return 11;
! 1406: if (desc->rate == 110)
! 1407: return 22;
! 1408: }
! 1409: return 2; /* should not get there */
! 1410: }
! 1411: #endif
! 1412:
! 1413: /*
! 1414: * Return the expected ack rate for a frame transmitted at rate `rate'.
! 1415: */
! 1416: int
! 1417: rt2560_ack_rate(struct ieee80211com *ic, int rate)
! 1418: {
! 1419: switch (rate) {
! 1420: /* CCK rates */
! 1421: case 2:
! 1422: return 2;
! 1423: case 4:
! 1424: case 11:
! 1425: case 22:
! 1426: return (ic->ic_curmode == IEEE80211_MODE_11B) ? 4 : rate;
! 1427:
! 1428: /* OFDM rates */
! 1429: case 12:
! 1430: case 18:
! 1431: return 12;
! 1432: case 24:
! 1433: case 36:
! 1434: return 24;
! 1435: case 48:
! 1436: case 72:
! 1437: case 96:
! 1438: case 108:
! 1439: return 48;
! 1440: }
! 1441:
! 1442: /* default to 1Mbps */
! 1443: return 2;
! 1444: }
! 1445:
! 1446: /*
! 1447: * Compute the duration (in us) needed to transmit `len' bytes at rate `rate'.
! 1448: * The function automatically determines the operating mode depending on the
! 1449: * given rate. `flags' indicates whether short preamble is in use or not.
! 1450: */
! 1451: uint16_t
! 1452: rt2560_txtime(int len, int rate, uint32_t flags)
! 1453: {
! 1454: uint16_t txtime;
! 1455:
! 1456: if (RAL_RATE_IS_OFDM(rate)) {
! 1457: /* IEEE Std 802.11g-2003, pp. 44 */
! 1458: txtime = (8 + 4 * len + 3 + rate - 1) / rate;
! 1459: txtime = 16 + 4 + 4 * txtime + 6;
! 1460: } else {
! 1461: /* IEEE Std 802.11b-1999, pp. 28 */
! 1462: txtime = (16 * len + rate - 1) / rate;
! 1463: if (rate != 2 && (flags & IEEE80211_F_SHPREAMBLE))
! 1464: txtime += 72 + 24;
! 1465: else
! 1466: txtime += 144 + 48;
! 1467: }
! 1468: return txtime;
! 1469: }
! 1470:
! 1471: uint8_t
! 1472: rt2560_plcp_signal(int rate)
! 1473: {
! 1474: switch (rate) {
! 1475: /* CCK rates (returned values are device-dependent) */
! 1476: case 2: return 0x0;
! 1477: case 4: return 0x1;
! 1478: case 11: return 0x2;
! 1479: case 22: return 0x3;
! 1480:
! 1481: /* OFDM rates (cf IEEE Std 802.11a-1999, pp. 14 Table 80) */
! 1482: case 12: return 0xb;
! 1483: case 18: return 0xf;
! 1484: case 24: return 0xa;
! 1485: case 36: return 0xe;
! 1486: case 48: return 0x9;
! 1487: case 72: return 0xd;
! 1488: case 96: return 0x8;
! 1489: case 108: return 0xc;
! 1490:
! 1491: /* unsupported rates (should not get there) */
! 1492: default: return 0xff;
! 1493: }
! 1494: }
! 1495:
! 1496: void
! 1497: rt2560_setup_tx_desc(struct rt2560_softc *sc, struct rt2560_tx_desc *desc,
! 1498: uint32_t flags, int len, int rate, int encrypt, bus_addr_t physaddr)
! 1499: {
! 1500: struct ieee80211com *ic = &sc->sc_ic;
! 1501: uint16_t plcp_length;
! 1502: int remainder;
! 1503:
! 1504: desc->flags = htole32(flags);
! 1505: desc->flags |= htole32(len << 16);
! 1506: desc->flags |= encrypt ? htole32(RT2560_TX_CIPHER_BUSY) :
! 1507: htole32(RT2560_TX_BUSY | RT2560_TX_VALID);
! 1508:
! 1509: desc->physaddr = htole32(physaddr);
! 1510: desc->wme = htole16(
! 1511: RT2560_AIFSN(2) |
! 1512: RT2560_LOGCWMIN(3) |
! 1513: RT2560_LOGCWMAX(8));
! 1514:
! 1515: /* setup PLCP fields */
! 1516: desc->plcp_signal = rt2560_plcp_signal(rate);
! 1517: desc->plcp_service = 4;
! 1518:
! 1519: len += IEEE80211_CRC_LEN;
! 1520: if (RAL_RATE_IS_OFDM(rate)) {
! 1521: desc->flags |= htole32(RT2560_TX_OFDM);
! 1522:
! 1523: plcp_length = len & 0xfff;
! 1524: desc->plcp_length_hi = plcp_length >> 6;
! 1525: desc->plcp_length_lo = plcp_length & 0x3f;
! 1526: } else {
! 1527: plcp_length = (16 * len + rate - 1) / rate;
! 1528: if (rate == 22) {
! 1529: remainder = (16 * len) % 22;
! 1530: if (remainder != 0 && remainder < 7)
! 1531: desc->plcp_service |= RT2560_PLCP_LENGEXT;
! 1532: }
! 1533: desc->plcp_length_hi = plcp_length >> 8;
! 1534: desc->plcp_length_lo = plcp_length & 0xff;
! 1535:
! 1536: if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
! 1537: desc->plcp_signal |= 0x08;
! 1538: }
! 1539: }
! 1540:
! 1541: int
! 1542: rt2560_tx_bcn(struct rt2560_softc *sc, struct mbuf *m0,
! 1543: struct ieee80211_node *ni)
! 1544: {
! 1545: struct ieee80211com *ic = &sc->sc_ic;
! 1546: struct rt2560_tx_desc *desc;
! 1547: struct rt2560_tx_data *data;
! 1548: int rate = 2, error;
! 1549:
! 1550: desc = &sc->bcnq.desc[sc->bcnq.cur];
! 1551: data = &sc->bcnq.data[sc->bcnq.cur];
! 1552:
! 1553: error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
! 1554: BUS_DMA_NOWAIT);
! 1555: if (error != 0) {
! 1556: printf("%s: could not map mbuf (error %d)\n",
! 1557: sc->sc_dev.dv_xname, error);
! 1558: m_freem(m0);
! 1559: return error;
! 1560: }
! 1561:
! 1562: data->m = m0;
! 1563: data->ni = ni;
! 1564:
! 1565: rt2560_setup_tx_desc(sc, desc, RT2560_TX_IFS_NEWBACKOFF |
! 1566: RT2560_TX_TIMESTAMP, m0->m_pkthdr.len, rate, 0,
! 1567: data->map->dm_segs->ds_addr);
! 1568:
! 1569: bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
! 1570: BUS_DMASYNC_PREWRITE);
! 1571: bus_dmamap_sync(sc->sc_dmat, sc->bcnq.map,
! 1572: sc->bcnq.cur * RT2560_TX_DESC_SIZE, RT2560_TX_DESC_SIZE,
! 1573: BUS_DMASYNC_PREWRITE);
! 1574:
! 1575: /*
! 1576: * Store pointer to ERP Information Element so that we can update it
! 1577: * dynamically when the slot time changes.
! 1578: * XXX: this is ugly since it depends on how net80211 builds beacon
! 1579: * frames but ieee80211_beacon_alloc() don't store offsets for us.
! 1580: */
! 1581: if (ic->ic_curmode == IEEE80211_MODE_11G) {
! 1582: sc->erp =
! 1583: mtod(m0, uint8_t *) +
! 1584: sizeof (struct ieee80211_frame) +
! 1585: 8 + 2 + 2 +
! 1586: ((ic->ic_flags & IEEE80211_F_HIDENWID) ?
! 1587: 1 : 2 + ni->ni_esslen) +
! 1588: 2 + min(ni->ni_rates.rs_nrates, IEEE80211_RATE_SIZE) +
! 1589: 2 + 1 +
! 1590: ((ic->ic_opmode == IEEE80211_M_IBSS) ? 4 : 6) +
! 1591: 2;
! 1592: }
! 1593:
! 1594: return 0;
! 1595: }
! 1596:
! 1597: int
! 1598: rt2560_tx_mgt(struct rt2560_softc *sc, struct mbuf *m0,
! 1599: struct ieee80211_node *ni)
! 1600: {
! 1601: struct ieee80211com *ic = &sc->sc_ic;
! 1602: struct ifnet *ifp = &ic->ic_if;
! 1603: struct rt2560_tx_desc *desc;
! 1604: struct rt2560_tx_data *data;
! 1605: struct ieee80211_frame *wh;
! 1606: uint16_t dur;
! 1607: uint32_t flags = 0;
! 1608: int rate = 2, error;
! 1609:
! 1610: desc = &sc->prioq.desc[sc->prioq.cur];
! 1611: data = &sc->prioq.data[sc->prioq.cur];
! 1612:
! 1613: wh = mtod(m0, struct ieee80211_frame *);
! 1614:
! 1615: if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
! 1616: m0 = ieee80211_wep_crypt(ifp, m0, 1);
! 1617: if (m0 == NULL)
! 1618: return ENOBUFS;
! 1619:
! 1620: /* packet header may have moved, reset our local pointer */
! 1621: wh = mtod(m0, struct ieee80211_frame *);
! 1622: }
! 1623:
! 1624: error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
! 1625: BUS_DMA_NOWAIT);
! 1626: if (error != 0) {
! 1627: printf("%s: could not map mbuf (error %d)\n",
! 1628: sc->sc_dev.dv_xname, error);
! 1629: m_freem(m0);
! 1630: return error;
! 1631: }
! 1632:
! 1633: #if NBPFILTER > 0
! 1634: if (sc->sc_drvbpf != NULL) {
! 1635: struct mbuf mb;
! 1636: struct rt2560_tx_radiotap_header *tap = &sc->sc_txtap;
! 1637:
! 1638: tap->wt_flags = 0;
! 1639: tap->wt_rate = rate;
! 1640: tap->wt_chan_freq = htole16(ic->ic_ibss_chan->ic_freq);
! 1641: tap->wt_chan_flags = htole16(ic->ic_ibss_chan->ic_flags);
! 1642: tap->wt_antenna = sc->tx_ant;
! 1643:
! 1644: mb.m_data = (caddr_t)tap;
! 1645: mb.m_len = sc->sc_txtap_len;
! 1646: mb.m_next = m0;
! 1647: mb.m_nextpkt = NULL;
! 1648: mb.m_type = 0;
! 1649: mb.m_flags = 0;
! 1650: bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
! 1651: }
! 1652: #endif
! 1653:
! 1654: data->m = m0;
! 1655: data->ni = ni;
! 1656:
! 1657: wh = mtod(m0, struct ieee80211_frame *);
! 1658:
! 1659: if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
! 1660: flags |= RT2560_TX_NEED_ACK;
! 1661:
! 1662: dur = rt2560_txtime(RAL_ACK_SIZE, rate, ic->ic_flags) +
! 1663: RAL_SIFS;
! 1664: *(uint16_t *)wh->i_dur = htole16(dur);
! 1665:
! 1666: /* tell hardware to set timestamp for probe responses */
! 1667: if ((wh->i_fc[0] &
! 1668: (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==
! 1669: (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP))
! 1670: flags |= RT2560_TX_TIMESTAMP;
! 1671: }
! 1672:
! 1673: rt2560_setup_tx_desc(sc, desc, flags, m0->m_pkthdr.len, rate, 0,
! 1674: data->map->dm_segs->ds_addr);
! 1675:
! 1676: bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
! 1677: BUS_DMASYNC_PREWRITE);
! 1678: bus_dmamap_sync(sc->sc_dmat, sc->prioq.map,
! 1679: sc->prioq.cur * RT2560_TX_DESC_SIZE, RT2560_TX_DESC_SIZE,
! 1680: BUS_DMASYNC_PREWRITE);
! 1681:
! 1682: DPRINTFN(10, ("sending mgt frame len=%u idx=%u rate=%u\n",
! 1683: m0->m_pkthdr.len, sc->prioq.cur, rate));
! 1684:
! 1685: /* kick prio */
! 1686: sc->prioq.queued++;
! 1687: sc->prioq.cur = (sc->prioq.cur + 1) % RT2560_PRIO_RING_COUNT;
! 1688: RAL_WRITE(sc, RT2560_TXCSR0, RT2560_KICK_PRIO);
! 1689:
! 1690: return 0;
! 1691: }
! 1692:
! 1693: int
! 1694: rt2560_tx_data(struct rt2560_softc *sc, struct mbuf *m0,
! 1695: struct ieee80211_node *ni)
! 1696: {
! 1697: struct ieee80211com *ic = &sc->sc_ic;
! 1698: struct ifnet *ifp = &ic->ic_if;
! 1699: struct rt2560_tx_ring *txq = &sc->txq;
! 1700: struct rt2560_tx_desc *desc;
! 1701: struct rt2560_tx_data *data;
! 1702: struct ieee80211_frame *wh;
! 1703: struct mbuf *mnew;
! 1704: uint16_t dur;
! 1705: uint32_t flags = 0;
! 1706: int pktlen, rate, needcts = 0, needrts = 0, error;
! 1707:
! 1708: wh = mtod(m0, struct ieee80211_frame *);
! 1709:
! 1710: if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
! 1711: m0 = ieee80211_wep_crypt(ifp, m0, 1);
! 1712: if (m0 == NULL)
! 1713: return ENOBUFS;
! 1714:
! 1715: /* packet header may have moved, reset our local pointer */
! 1716: wh = mtod(m0, struct ieee80211_frame *);
! 1717: }
! 1718:
! 1719: /* compute actual packet length (including CRC and crypto overhead) */
! 1720: pktlen = m0->m_pkthdr.len + IEEE80211_CRC_LEN;
! 1721:
! 1722: /* pickup a rate */
! 1723: if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
! 1724: ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
! 1725: IEEE80211_FC0_TYPE_MGT)) {
! 1726: /* mgmt/multicast frames are sent at the lowest avail. rate */
! 1727: rate = ni->ni_rates.rs_rates[0];
! 1728: } else if (ic->ic_fixed_rate != -1) {
! 1729: rate = ic->ic_sup_rates[ic->ic_curmode].
! 1730: rs_rates[ic->ic_fixed_rate];
! 1731: } else
! 1732: rate = ni->ni_rates.rs_rates[ni->ni_txrate];
! 1733: if (rate == 0)
! 1734: rate = 2; /* XXX should not happen */
! 1735: rate &= IEEE80211_RATE_VAL;
! 1736:
! 1737: /*
! 1738: * Packet Bursting: backoff after ppb=8 frames to give other STAs a
! 1739: * chance to contend for the wireless medium.
! 1740: */
! 1741: if (ic->ic_opmode == IEEE80211_M_STA && (ni->ni_txseq & 7))
! 1742: flags |= RT2560_TX_IFS_SIFS;
! 1743:
! 1744: /* check if RTS/CTS or CTS-to-self protection must be used */
! 1745: if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
! 1746: /* multicast frames are not sent at OFDM rates in 802.11b/g */
! 1747: if (pktlen > ic->ic_rtsthreshold) {
! 1748: needrts = 1; /* RTS/CTS based on frame length */
! 1749: } else if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
! 1750: RAL_RATE_IS_OFDM(rate)) {
! 1751: if (ic->ic_protmode == IEEE80211_PROT_CTSONLY)
! 1752: needcts = 1; /* CTS-to-self */
! 1753: else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS)
! 1754: needrts = 1; /* RTS/CTS */
! 1755: }
! 1756: }
! 1757: if (needrts || needcts) {
! 1758: struct mbuf *mprot;
! 1759: int protrate, ackrate;
! 1760: uint16_t dur;
! 1761:
! 1762: protrate = 2; /* XXX */
! 1763: ackrate = rt2560_ack_rate(ic, rate);
! 1764:
! 1765: dur = rt2560_txtime(pktlen, rate, ic->ic_flags) +
! 1766: rt2560_txtime(RAL_ACK_SIZE, ackrate, ic->ic_flags) +
! 1767: 2 * RAL_SIFS;
! 1768: if (needrts) {
! 1769: dur += rt2560_txtime(RAL_CTS_SIZE, rt2560_ack_rate(ic,
! 1770: protrate), ic->ic_flags) + RAL_SIFS;
! 1771: mprot = ieee80211_get_rts(ic, wh, dur);
! 1772: } else {
! 1773: mprot = ieee80211_get_cts_to_self(ic, dur);
! 1774: }
! 1775: if (mprot == NULL) {
! 1776: printf("%s: could not allocate protection frame\n",
! 1777: sc->sc_dev.dv_xname);
! 1778: m_freem(m0);
! 1779: return ENOBUFS;
! 1780: }
! 1781:
! 1782: desc = &txq->desc[txq->cur_encrypt];
! 1783: data = &txq->data[txq->cur_encrypt];
! 1784:
! 1785: error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, mprot,
! 1786: BUS_DMA_NOWAIT);
! 1787: if (error != 0) {
! 1788: printf("%s: could not map mbuf (error %d)\n",
! 1789: sc->sc_dev.dv_xname, error);
! 1790: m_freem(mprot);
! 1791: m_freem(m0);
! 1792: return error;
! 1793: }
! 1794:
! 1795: data->m = mprot;
! 1796: /* avoid multiple free() of the same node for each fragment */
! 1797: data->ni = ieee80211_ref_node(ni);
! 1798:
! 1799: /* XXX may want to pass the protection frame to BPF */
! 1800:
! 1801: rt2560_setup_tx_desc(sc, desc,
! 1802: (needrts ? RT2560_TX_NEED_ACK : 0) | RT2560_TX_MORE_FRAG,
! 1803: mprot->m_pkthdr.len, protrate, 1,
! 1804: data->map->dm_segs->ds_addr);
! 1805:
! 1806: bus_dmamap_sync(sc->sc_dmat, data->map, 0,
! 1807: data->map->dm_mapsize, BUS_DMASYNC_PREWRITE);
! 1808: bus_dmamap_sync(sc->sc_dmat, txq->map,
! 1809: txq->cur_encrypt * RT2560_TX_DESC_SIZE,
! 1810: RT2560_TX_DESC_SIZE, BUS_DMASYNC_PREWRITE);
! 1811:
! 1812: txq->queued++;
! 1813: if (++txq->cur_encrypt >= txq->count)
! 1814: txq->cur_encrypt = 0;
! 1815:
! 1816: flags |= RT2560_TX_LONG_RETRY | RT2560_TX_IFS_SIFS;
! 1817: }
! 1818:
! 1819: data = &txq->data[txq->cur_encrypt];
! 1820: desc = &txq->desc[txq->cur_encrypt];
! 1821:
! 1822: error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
! 1823: BUS_DMA_NOWAIT);
! 1824: if (error != 0 && error != EFBIG) {
! 1825: printf("%s: could not map mbuf (error %d)\n",
! 1826: sc->sc_dev.dv_xname, error);
! 1827: m_freem(m0);
! 1828: return error;
! 1829: }
! 1830: if (error != 0) {
! 1831: /* too many fragments, linearize */
! 1832:
! 1833: MGETHDR(mnew, M_DONTWAIT, MT_DATA);
! 1834: if (mnew == NULL) {
! 1835: m_freem(m0);
! 1836: return ENOMEM;
! 1837: }
! 1838: M_DUP_PKTHDR(mnew, m0);
! 1839: if (m0->m_pkthdr.len > MHLEN) {
! 1840: MCLGET(mnew, M_DONTWAIT);
! 1841: if (!(mnew->m_flags & M_EXT)) {
! 1842: m_freem(m0);
! 1843: m_freem(mnew);
! 1844: return ENOMEM;
! 1845: }
! 1846: }
! 1847:
! 1848: m_copydata(m0, 0, m0->m_pkthdr.len, mtod(mnew, caddr_t));
! 1849: m_freem(m0);
! 1850: mnew->m_len = mnew->m_pkthdr.len;
! 1851: m0 = mnew;
! 1852:
! 1853: error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m0,
! 1854: BUS_DMA_NOWAIT);
! 1855: if (error != 0) {
! 1856: printf("%s: could not map mbuf (error %d)\n",
! 1857: sc->sc_dev.dv_xname, error);
! 1858: m_freem(m0);
! 1859: return error;
! 1860: }
! 1861:
! 1862: /* packet header have moved, reset our local pointer */
! 1863: wh = mtod(m0, struct ieee80211_frame *);
! 1864: }
! 1865:
! 1866: #if NBPFILTER > 0
! 1867: if (sc->sc_drvbpf != NULL) {
! 1868: struct mbuf mb;
! 1869: struct rt2560_tx_radiotap_header *tap = &sc->sc_txtap;
! 1870:
! 1871: tap->wt_flags = 0;
! 1872: tap->wt_rate = rate;
! 1873: tap->wt_chan_freq = htole16(ic->ic_ibss_chan->ic_freq);
! 1874: tap->wt_chan_flags = htole16(ic->ic_ibss_chan->ic_flags);
! 1875: tap->wt_antenna = sc->tx_ant;
! 1876:
! 1877: mb.m_data = (caddr_t)tap;
! 1878: mb.m_len = sc->sc_txtap_len;
! 1879: mb.m_next = m0;
! 1880: mb.m_nextpkt = NULL;
! 1881: mb.m_type = 0;
! 1882: mb.m_flags = 0;
! 1883: bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
! 1884: }
! 1885: #endif
! 1886:
! 1887: data->m = m0;
! 1888: data->ni = ni;
! 1889:
! 1890: if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
! 1891: flags |= RT2560_TX_NEED_ACK;
! 1892:
! 1893: dur = rt2560_txtime(RAL_ACK_SIZE, rt2560_ack_rate(ic, rate),
! 1894: ic->ic_flags) + RAL_SIFS;
! 1895: *(uint16_t *)wh->i_dur = htole16(dur);
! 1896: }
! 1897:
! 1898: rt2560_setup_tx_desc(sc, desc, flags, m0->m_pkthdr.len, rate, 1,
! 1899: data->map->dm_segs->ds_addr);
! 1900:
! 1901: bus_dmamap_sync(sc->sc_dmat, data->map, 0, data->map->dm_mapsize,
! 1902: BUS_DMASYNC_PREWRITE);
! 1903: bus_dmamap_sync(sc->sc_dmat, txq->map,
! 1904: txq->cur_encrypt * RT2560_TX_DESC_SIZE, RT2560_TX_DESC_SIZE,
! 1905: BUS_DMASYNC_PREWRITE);
! 1906:
! 1907: DPRINTFN(10, ("sending frame len=%u idx=%u rate=%u\n",
! 1908: m0->m_pkthdr.len, txq->cur_encrypt, rate));
! 1909:
! 1910: /* kick encrypt */
! 1911: txq->queued++;
! 1912: if (++txq->cur_encrypt >= txq->count)
! 1913: txq->cur_encrypt = 0;
! 1914: RAL_WRITE(sc, RT2560_SECCSR1, RT2560_KICK_ENCRYPT);
! 1915:
! 1916: return 0;
! 1917: }
! 1918:
! 1919: void
! 1920: rt2560_start(struct ifnet *ifp)
! 1921: {
! 1922: struct rt2560_softc *sc = ifp->if_softc;
! 1923: struct ieee80211com *ic = &sc->sc_ic;
! 1924: struct mbuf *m0;
! 1925: struct ieee80211_node *ni;
! 1926:
! 1927: /*
! 1928: * net80211 may still try to send management frames even if the
! 1929: * IFF_RUNNING flag is not set...
! 1930: */
! 1931: if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
! 1932: return;
! 1933:
! 1934: for (;;) {
! 1935: IF_POLL(&ic->ic_mgtq, m0);
! 1936: if (m0 != NULL) {
! 1937: if (sc->prioq.queued >= RT2560_PRIO_RING_COUNT) {
! 1938: ifp->if_flags |= IFF_OACTIVE;
! 1939: break;
! 1940: }
! 1941: IF_DEQUEUE(&ic->ic_mgtq, m0);
! 1942:
! 1943: ni = (struct ieee80211_node *)m0->m_pkthdr.rcvif;
! 1944: m0->m_pkthdr.rcvif = NULL;
! 1945: #if NBPFILTER > 0
! 1946: if (ic->ic_rawbpf != NULL)
! 1947: bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT);
! 1948: #endif
! 1949: if (rt2560_tx_mgt(sc, m0, ni) != 0)
! 1950: break;
! 1951:
! 1952: } else {
! 1953: if (ic->ic_state != IEEE80211_S_RUN)
! 1954: break;
! 1955: IFQ_POLL(&ifp->if_snd, m0);
! 1956: if (m0 == NULL)
! 1957: break;
! 1958: if (sc->txq.queued >= RT2560_TX_RING_COUNT - 1) {
! 1959: ifp->if_flags |= IFF_OACTIVE;
! 1960: break;
! 1961: }
! 1962: IFQ_DEQUEUE(&ifp->if_snd, m0);
! 1963: #if NBPFILTER > 0
! 1964: if (ifp->if_bpf != NULL)
! 1965: bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
! 1966: #endif
! 1967: m0 = ieee80211_encap(ifp, m0, &ni);
! 1968: if (m0 == NULL)
! 1969: continue;
! 1970: #if NBPFILTER > 0
! 1971: if (ic->ic_rawbpf != NULL)
! 1972: bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT);
! 1973: #endif
! 1974: if (rt2560_tx_data(sc, m0, ni) != 0) {
! 1975: if (ni != NULL)
! 1976: ieee80211_release_node(ic, ni);
! 1977: ifp->if_oerrors++;
! 1978: break;
! 1979: }
! 1980: }
! 1981:
! 1982: sc->sc_tx_timer = 5;
! 1983: ifp->if_timer = 1;
! 1984: }
! 1985: }
! 1986:
! 1987: void
! 1988: rt2560_watchdog(struct ifnet *ifp)
! 1989: {
! 1990: struct rt2560_softc *sc = ifp->if_softc;
! 1991:
! 1992: ifp->if_timer = 0;
! 1993:
! 1994: if (sc->sc_tx_timer > 0) {
! 1995: if (--sc->sc_tx_timer == 0) {
! 1996: printf("%s: device timeout\n", sc->sc_dev.dv_xname);
! 1997: rt2560_init(ifp);
! 1998: ifp->if_oerrors++;
! 1999: return;
! 2000: }
! 2001: ifp->if_timer = 1;
! 2002: }
! 2003:
! 2004: ieee80211_watchdog(ifp);
! 2005: }
! 2006:
! 2007: int
! 2008: rt2560_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
! 2009: {
! 2010: struct rt2560_softc *sc = ifp->if_softc;
! 2011: struct ieee80211com *ic = &sc->sc_ic;
! 2012: struct ifaddr *ifa;
! 2013: struct ifreq *ifr;
! 2014: int s, error = 0;
! 2015:
! 2016: s = splnet();
! 2017:
! 2018: switch (cmd) {
! 2019: case SIOCSIFADDR:
! 2020: ifa = (struct ifaddr *)data;
! 2021: ifp->if_flags |= IFF_UP;
! 2022: #ifdef INET
! 2023: if (ifa->ifa_addr->sa_family == AF_INET)
! 2024: arp_ifinit(&ic->ic_ac, ifa);
! 2025: #endif
! 2026: /* FALLTHROUGH */
! 2027: case SIOCSIFFLAGS:
! 2028: if (ifp->if_flags & IFF_UP) {
! 2029: if (ifp->if_flags & IFF_RUNNING)
! 2030: rt2560_update_promisc(sc);
! 2031: else
! 2032: rt2560_init(ifp);
! 2033: } else {
! 2034: if (ifp->if_flags & IFF_RUNNING)
! 2035: rt2560_stop(ifp, 1);
! 2036: }
! 2037: break;
! 2038:
! 2039: case SIOCADDMULTI:
! 2040: case SIOCDELMULTI:
! 2041: ifr = (struct ifreq *)data;
! 2042: error = (cmd == SIOCADDMULTI) ?
! 2043: ether_addmulti(ifr, &ic->ic_ac) :
! 2044: ether_delmulti(ifr, &ic->ic_ac);
! 2045:
! 2046: if (error == ENETRESET)
! 2047: error = 0;
! 2048: break;
! 2049:
! 2050: case SIOCS80211CHANNEL:
! 2051: /*
! 2052: * This allows for fast channel switching in monitor mode
! 2053: * (used by kismet). In IBSS mode, we must explicitly reset
! 2054: * the interface to generate a new beacon frame.
! 2055: */
! 2056: error = ieee80211_ioctl(ifp, cmd, data);
! 2057: if (error == ENETRESET &&
! 2058: ic->ic_opmode == IEEE80211_M_MONITOR) {
! 2059: if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
! 2060: (IFF_UP | IFF_RUNNING))
! 2061: rt2560_set_chan(sc, ic->ic_ibss_chan);
! 2062: error = 0;
! 2063: }
! 2064: break;
! 2065:
! 2066: default:
! 2067: error = ieee80211_ioctl(ifp, cmd, data);
! 2068: }
! 2069:
! 2070: if (error == ENETRESET) {
! 2071: if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
! 2072: (IFF_UP | IFF_RUNNING))
! 2073: rt2560_init(ifp);
! 2074: error = 0;
! 2075: }
! 2076:
! 2077: splx(s);
! 2078:
! 2079: return error;
! 2080: }
! 2081:
! 2082: void
! 2083: rt2560_bbp_write(struct rt2560_softc *sc, uint8_t reg, uint8_t val)
! 2084: {
! 2085: uint32_t tmp;
! 2086: int ntries;
! 2087:
! 2088: for (ntries = 0; ntries < 100; ntries++) {
! 2089: if (!(RAL_READ(sc, RT2560_BBPCSR) & RT2560_BBP_BUSY))
! 2090: break;
! 2091: DELAY(1);
! 2092: }
! 2093: if (ntries == 100) {
! 2094: printf("%s: could not write to BBP\n", sc->sc_dev.dv_xname);
! 2095: return;
! 2096: }
! 2097:
! 2098: tmp = RT2560_BBP_WRITE | RT2560_BBP_BUSY | reg << 8 | val;
! 2099: RAL_WRITE(sc, RT2560_BBPCSR, tmp);
! 2100:
! 2101: DPRINTFN(15, ("BBP R%u <- 0x%02x\n", reg, val));
! 2102: }
! 2103:
! 2104: uint8_t
! 2105: rt2560_bbp_read(struct rt2560_softc *sc, uint8_t reg)
! 2106: {
! 2107: uint32_t val;
! 2108: int ntries;
! 2109:
! 2110: val = RT2560_BBP_BUSY | reg << 8;
! 2111: RAL_WRITE(sc, RT2560_BBPCSR, val);
! 2112:
! 2113: for (ntries = 0; ntries < 100; ntries++) {
! 2114: val = RAL_READ(sc, RT2560_BBPCSR);
! 2115: if (!(val & RT2560_BBP_BUSY))
! 2116: return val & 0xff;
! 2117: DELAY(1);
! 2118: }
! 2119:
! 2120: printf("%s: could not read from BBP\n", sc->sc_dev.dv_xname);
! 2121: return 0;
! 2122: }
! 2123:
! 2124: void
! 2125: rt2560_rf_write(struct rt2560_softc *sc, uint8_t reg, uint32_t val)
! 2126: {
! 2127: uint32_t tmp;
! 2128: int ntries;
! 2129:
! 2130: for (ntries = 0; ntries < 100; ntries++) {
! 2131: if (!(RAL_READ(sc, RT2560_RFCSR) & RT2560_RF_BUSY))
! 2132: break;
! 2133: DELAY(1);
! 2134: }
! 2135: if (ntries == 100) {
! 2136: printf("%s: could not write to RF\n", sc->sc_dev.dv_xname);
! 2137: return;
! 2138: }
! 2139:
! 2140: tmp = RT2560_RF_BUSY | RT2560_RF_20BIT | (val & 0xfffff) << 2 |
! 2141: (reg & 0x3);
! 2142: RAL_WRITE(sc, RT2560_RFCSR, tmp);
! 2143:
! 2144: /* remember last written value in sc */
! 2145: sc->rf_regs[reg] = val;
! 2146:
! 2147: DPRINTFN(15, ("RF R[%u] <- 0x%05x\n", reg & 0x3, val & 0xfffff));
! 2148: }
! 2149:
! 2150: void
! 2151: rt2560_set_chan(struct rt2560_softc *sc, struct ieee80211_channel *c)
! 2152: {
! 2153: struct ieee80211com *ic = &sc->sc_ic;
! 2154: uint8_t power, tmp;
! 2155: u_int chan;
! 2156:
! 2157: chan = ieee80211_chan2ieee(ic, c);
! 2158: if (chan == 0 || chan == IEEE80211_CHAN_ANY)
! 2159: return;
! 2160:
! 2161: power = min(sc->txpow[chan - 1], 31);
! 2162:
! 2163: DPRINTFN(2, ("setting channel to %u, txpower to %u\n", chan, power));
! 2164:
! 2165: switch (sc->rf_rev) {
! 2166: case RT2560_RF_2522:
! 2167: rt2560_rf_write(sc, RT2560_RF1, 0x00814);
! 2168: rt2560_rf_write(sc, RT2560_RF2, rt2560_rf2522_r2[chan - 1]);
! 2169: rt2560_rf_write(sc, RT2560_RF3, power << 7 | 0x00040);
! 2170: break;
! 2171:
! 2172: case RT2560_RF_2523:
! 2173: rt2560_rf_write(sc, RT2560_RF1, 0x08804);
! 2174: rt2560_rf_write(sc, RT2560_RF2, rt2560_rf2523_r2[chan - 1]);
! 2175: rt2560_rf_write(sc, RT2560_RF3, power << 7 | 0x38044);
! 2176: rt2560_rf_write(sc, RT2560_RF4,
! 2177: (chan == 14) ? 0x00280 : 0x00286);
! 2178: break;
! 2179:
! 2180: case RT2560_RF_2524:
! 2181: rt2560_rf_write(sc, RT2560_RF1, 0x0c808);
! 2182: rt2560_rf_write(sc, RT2560_RF2, rt2560_rf2524_r2[chan - 1]);
! 2183: rt2560_rf_write(sc, RT2560_RF3, power << 7 | 0x00040);
! 2184: rt2560_rf_write(sc, RT2560_RF4,
! 2185: (chan == 14) ? 0x00280 : 0x00286);
! 2186: break;
! 2187:
! 2188: case RT2560_RF_2525:
! 2189: rt2560_rf_write(sc, RT2560_RF1, 0x08808);
! 2190: rt2560_rf_write(sc, RT2560_RF2, rt2560_rf2525_hi_r2[chan - 1]);
! 2191: rt2560_rf_write(sc, RT2560_RF3, power << 7 | 0x18044);
! 2192: rt2560_rf_write(sc, RT2560_RF4,
! 2193: (chan == 14) ? 0x00280 : 0x00286);
! 2194:
! 2195: rt2560_rf_write(sc, RT2560_RF1, 0x08808);
! 2196: rt2560_rf_write(sc, RT2560_RF2, rt2560_rf2525_r2[chan - 1]);
! 2197: rt2560_rf_write(sc, RT2560_RF3, power << 7 | 0x18044);
! 2198: rt2560_rf_write(sc, RT2560_RF4,
! 2199: (chan == 14) ? 0x00280 : 0x00286);
! 2200: break;
! 2201:
! 2202: case RT2560_RF_2525E:
! 2203: rt2560_rf_write(sc, RT2560_RF1, 0x08808);
! 2204: rt2560_rf_write(sc, RT2560_RF2, rt2560_rf2525e_r2[chan - 1]);
! 2205: rt2560_rf_write(sc, RT2560_RF3, power << 7 | 0x18044);
! 2206: rt2560_rf_write(sc, RT2560_RF4,
! 2207: (chan == 14) ? 0x00286 : 0x00282);
! 2208: break;
! 2209:
! 2210: case RT2560_RF_2526:
! 2211: rt2560_rf_write(sc, RT2560_RF2, rt2560_rf2526_hi_r2[chan - 1]);
! 2212: rt2560_rf_write(sc, RT2560_RF4,
! 2213: (chan & 1) ? 0x00386 : 0x00381);
! 2214: rt2560_rf_write(sc, RT2560_RF1, 0x08804);
! 2215:
! 2216: rt2560_rf_write(sc, RT2560_RF2, rt2560_rf2526_r2[chan - 1]);
! 2217: rt2560_rf_write(sc, RT2560_RF3, power << 7 | 0x18044);
! 2218: rt2560_rf_write(sc, RT2560_RF4,
! 2219: (chan & 1) ? 0x00386 : 0x00381);
! 2220: break;
! 2221: }
! 2222:
! 2223: if (ic->ic_opmode != IEEE80211_M_MONITOR &&
! 2224: ic->ic_state != IEEE80211_S_SCAN) {
! 2225: /* set Japan filter bit for channel 14 */
! 2226: tmp = rt2560_bbp_read(sc, 70);
! 2227:
! 2228: tmp &= ~RT2560_JAPAN_FILTER;
! 2229: if (chan == 14)
! 2230: tmp |= RT2560_JAPAN_FILTER;
! 2231:
! 2232: rt2560_bbp_write(sc, 70, tmp);
! 2233:
! 2234: DELAY(1000); /* RF needs a 1ms delay here */
! 2235: rt2560_disable_rf_tune(sc);
! 2236:
! 2237: /* clear CRC errors */
! 2238: RAL_READ(sc, RT2560_CNT0);
! 2239: }
! 2240: }
! 2241:
! 2242: /*
! 2243: * Disable RF auto-tuning.
! 2244: */
! 2245: void
! 2246: rt2560_disable_rf_tune(struct rt2560_softc *sc)
! 2247: {
! 2248: uint32_t tmp;
! 2249:
! 2250: if (sc->rf_rev != RT2560_RF_2523) {
! 2251: tmp = sc->rf_regs[RT2560_RF1] & ~RT2560_RF1_AUTOTUNE;
! 2252: rt2560_rf_write(sc, RT2560_RF1, tmp);
! 2253: }
! 2254:
! 2255: tmp = sc->rf_regs[RT2560_RF3] & ~RT2560_RF3_AUTOTUNE;
! 2256: rt2560_rf_write(sc, RT2560_RF3, tmp);
! 2257:
! 2258: DPRINTFN(2, ("disabling RF autotune\n"));
! 2259: }
! 2260:
! 2261: /*
! 2262: * Refer to IEEE Std 802.11-1999 pp. 123 for more information on TSF
! 2263: * synchronization.
! 2264: */
! 2265: void
! 2266: rt2560_enable_tsf_sync(struct rt2560_softc *sc)
! 2267: {
! 2268: struct ieee80211com *ic = &sc->sc_ic;
! 2269: uint16_t logcwmin, preload;
! 2270: uint32_t tmp;
! 2271:
! 2272: /* first, disable TSF synchronization */
! 2273: RAL_WRITE(sc, RT2560_CSR14, 0);
! 2274:
! 2275: tmp = 16 * ic->ic_bss->ni_intval;
! 2276: RAL_WRITE(sc, RT2560_CSR12, tmp);
! 2277:
! 2278: RAL_WRITE(sc, RT2560_CSR13, 0);
! 2279:
! 2280: logcwmin = 5;
! 2281: preload = (ic->ic_opmode == IEEE80211_M_STA) ? 384 : 1024;
! 2282: tmp = logcwmin << 16 | preload;
! 2283: RAL_WRITE(sc, RT2560_BCNOCSR, tmp);
! 2284:
! 2285: /* finally, enable TSF synchronization */
! 2286: tmp = RT2560_ENABLE_TSF | RT2560_ENABLE_TBCN;
! 2287: if (ic->ic_opmode == IEEE80211_M_STA)
! 2288: tmp |= RT2560_ENABLE_TSF_SYNC(1);
! 2289: else
! 2290: tmp |= RT2560_ENABLE_TSF_SYNC(2) |
! 2291: RT2560_ENABLE_BEACON_GENERATOR;
! 2292: RAL_WRITE(sc, RT2560_CSR14, tmp);
! 2293:
! 2294: DPRINTF(("enabling TSF synchronization\n"));
! 2295: }
! 2296:
! 2297: void
! 2298: rt2560_update_plcp(struct rt2560_softc *sc)
! 2299: {
! 2300: struct ieee80211com *ic = &sc->sc_ic;
! 2301:
! 2302: /* no short preamble for 1Mbps */
! 2303: RAL_WRITE(sc, RT2560_PLCP1MCSR, 0x00700400);
! 2304:
! 2305: if (!(ic->ic_flags & IEEE80211_F_SHPREAMBLE)) {
! 2306: /* values taken from the reference driver */
! 2307: RAL_WRITE(sc, RT2560_PLCP2MCSR, 0x00380401);
! 2308: RAL_WRITE(sc, RT2560_PLCP5p5MCSR, 0x00150402);
! 2309: RAL_WRITE(sc, RT2560_PLCP11MCSR, 0x000b8403);
! 2310: } else {
! 2311: /* same values as above or'ed 0x8 */
! 2312: RAL_WRITE(sc, RT2560_PLCP2MCSR, 0x00380409);
! 2313: RAL_WRITE(sc, RT2560_PLCP5p5MCSR, 0x0015040a);
! 2314: RAL_WRITE(sc, RT2560_PLCP11MCSR, 0x000b840b);
! 2315: }
! 2316:
! 2317: DPRINTF(("updating PLCP for %s preamble\n",
! 2318: (ic->ic_flags & IEEE80211_F_SHPREAMBLE) ? "short" : "long"));
! 2319: }
! 2320:
! 2321: void
! 2322: rt2560_updateslot(struct ieee80211com *ic)
! 2323: {
! 2324: struct rt2560_softc *sc = ic->ic_if.if_softc;
! 2325:
! 2326: if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
! 2327: /*
! 2328: * In HostAP mode, we defer setting of new slot time until
! 2329: * updated ERP Information Element has propagated to all
! 2330: * associated STAs.
! 2331: */
! 2332: sc->sc_flags |= RT2560_UPDATE_SLOT;
! 2333: } else
! 2334: rt2560_set_slottime(sc);
! 2335: }
! 2336:
! 2337: /*
! 2338: * IEEE 802.11a (and possibly 802.11g) use short slot time. Refer to
! 2339: * IEEE Std 802.11-1999 pp. 85 to know how these values are computed.
! 2340: */
! 2341: void
! 2342: rt2560_set_slottime(struct rt2560_softc *sc)
! 2343: {
! 2344: struct ieee80211com *ic = &sc->sc_ic;
! 2345: uint8_t slottime;
! 2346: uint16_t sifs, pifs, difs, eifs;
! 2347: uint32_t tmp;
! 2348:
! 2349: slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
! 2350:
! 2351: /* define the MAC slot boundaries */
! 2352: sifs = RAL_SIFS - RT2560_RXTX_TURNAROUND;
! 2353: pifs = sifs + slottime;
! 2354: difs = sifs + 2 * slottime;
! 2355: eifs = (ic->ic_curmode == IEEE80211_MODE_11B) ? 364 : 60;
! 2356:
! 2357: tmp = RAL_READ(sc, RT2560_CSR11);
! 2358: tmp = (tmp & ~0x1f00) | slottime << 8;
! 2359: RAL_WRITE(sc, RT2560_CSR11, tmp);
! 2360:
! 2361: tmp = pifs << 16 | sifs;
! 2362: RAL_WRITE(sc, RT2560_CSR18, tmp);
! 2363:
! 2364: tmp = eifs << 16 | difs;
! 2365: RAL_WRITE(sc, RT2560_CSR19, tmp);
! 2366:
! 2367: DPRINTF(("setting slottime to %uus\n", slottime));
! 2368: }
! 2369:
! 2370: void
! 2371: rt2560_set_basicrates(struct rt2560_softc *sc)
! 2372: {
! 2373: struct ieee80211com *ic = &sc->sc_ic;
! 2374:
! 2375: /* update basic rate set */
! 2376: if (ic->ic_curmode == IEEE80211_MODE_11B) {
! 2377: /* 11b basic rates: 1, 2Mbps */
! 2378: RAL_WRITE(sc, RT2560_ARSP_PLCP_1, 0x3);
! 2379: } else {
! 2380: /* 11b/g basic rates: 1, 2, 5.5, 11Mbps */
! 2381: RAL_WRITE(sc, RT2560_ARSP_PLCP_1, 0xf);
! 2382: }
! 2383: }
! 2384:
! 2385: void
! 2386: rt2560_update_led(struct rt2560_softc *sc, int led1, int led2)
! 2387: {
! 2388: uint32_t tmp;
! 2389:
! 2390: /* set ON period to 70ms and OFF period to 30ms */
! 2391: tmp = led1 << 16 | led2 << 17 | 70 << 8 | 30;
! 2392: RAL_WRITE(sc, RT2560_LEDCSR, tmp);
! 2393: }
! 2394:
! 2395: void
! 2396: rt2560_set_bssid(struct rt2560_softc *sc, uint8_t *bssid)
! 2397: {
! 2398: uint32_t tmp;
! 2399:
! 2400: tmp = bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24;
! 2401: RAL_WRITE(sc, RT2560_CSR5, tmp);
! 2402:
! 2403: tmp = bssid[4] | bssid[5] << 8;
! 2404: RAL_WRITE(sc, RT2560_CSR6, tmp);
! 2405:
! 2406: DPRINTF(("setting BSSID to %s\n", ether_sprintf(bssid)));
! 2407: }
! 2408:
! 2409: void
! 2410: rt2560_set_macaddr(struct rt2560_softc *sc, uint8_t *addr)
! 2411: {
! 2412: uint32_t tmp;
! 2413:
! 2414: tmp = addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24;
! 2415: RAL_WRITE(sc, RT2560_CSR3, tmp);
! 2416:
! 2417: tmp = addr[4] | addr[5] << 8;
! 2418: RAL_WRITE(sc, RT2560_CSR4, tmp);
! 2419:
! 2420: DPRINTF(("setting MAC address to %s\n", ether_sprintf(addr)));
! 2421: }
! 2422:
! 2423: void
! 2424: rt2560_get_macaddr(struct rt2560_softc *sc, uint8_t *addr)
! 2425: {
! 2426: uint32_t tmp;
! 2427:
! 2428: tmp = RAL_READ(sc, RT2560_CSR3);
! 2429: addr[0] = tmp & 0xff;
! 2430: addr[1] = (tmp >> 8) & 0xff;
! 2431: addr[2] = (tmp >> 16) & 0xff;
! 2432: addr[3] = (tmp >> 24);
! 2433:
! 2434: tmp = RAL_READ(sc, RT2560_CSR4);
! 2435: addr[4] = tmp & 0xff;
! 2436: addr[5] = (tmp >> 8) & 0xff;
! 2437: }
! 2438:
! 2439: void
! 2440: rt2560_update_promisc(struct rt2560_softc *sc)
! 2441: {
! 2442: struct ifnet *ifp = &sc->sc_ic.ic_if;
! 2443: uint32_t tmp;
! 2444:
! 2445: tmp = RAL_READ(sc, RT2560_RXCSR0);
! 2446:
! 2447: tmp &= ~RT2560_DROP_NOT_TO_ME;
! 2448: if (!(ifp->if_flags & IFF_PROMISC))
! 2449: tmp |= RT2560_DROP_NOT_TO_ME;
! 2450:
! 2451: RAL_WRITE(sc, RT2560_RXCSR0, tmp);
! 2452:
! 2453: DPRINTF(("%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ?
! 2454: "entering" : "leaving"));
! 2455: }
! 2456:
! 2457: void
! 2458: rt2560_set_txantenna(struct rt2560_softc *sc, int antenna)
! 2459: {
! 2460: uint32_t tmp;
! 2461: uint8_t tx;
! 2462:
! 2463: tx = rt2560_bbp_read(sc, RT2560_BBP_TX) & ~RT2560_BBP_ANTMASK;
! 2464: if (antenna == 1)
! 2465: tx |= RT2560_BBP_ANTA;
! 2466: else if (antenna == 2)
! 2467: tx |= RT2560_BBP_ANTB;
! 2468: else
! 2469: tx |= RT2560_BBP_DIVERSITY;
! 2470:
! 2471: /* need to force I/Q flip for RF 2525e, 2526 and 5222 */
! 2472: if (sc->rf_rev == RT2560_RF_2525E || sc->rf_rev == RT2560_RF_2526 ||
! 2473: sc->rf_rev == RT2560_RF_5222)
! 2474: tx |= RT2560_BBP_FLIPIQ;
! 2475:
! 2476: rt2560_bbp_write(sc, RT2560_BBP_TX, tx);
! 2477:
! 2478: /* update values for CCK and OFDM in BBPCSR1 */
! 2479: tmp = RAL_READ(sc, RT2560_BBPCSR1) & ~0x00070007;
! 2480: tmp |= (tx & 0x7) << 16 | (tx & 0x7);
! 2481: RAL_WRITE(sc, RT2560_BBPCSR1, tmp);
! 2482: }
! 2483:
! 2484: void
! 2485: rt2560_set_rxantenna(struct rt2560_softc *sc, int antenna)
! 2486: {
! 2487: uint8_t rx;
! 2488:
! 2489: rx = rt2560_bbp_read(sc, RT2560_BBP_RX) & ~RT2560_BBP_ANTMASK;
! 2490: if (antenna == 1)
! 2491: rx |= RT2560_BBP_ANTA;
! 2492: else if (antenna == 2)
! 2493: rx |= RT2560_BBP_ANTB;
! 2494: else
! 2495: rx |= RT2560_BBP_DIVERSITY;
! 2496:
! 2497: /* need to force no I/Q flip for RF 2525e and 2526 */
! 2498: if (sc->rf_rev == RT2560_RF_2525E || sc->rf_rev == RT2560_RF_2526)
! 2499: rx &= ~RT2560_BBP_FLIPIQ;
! 2500:
! 2501: rt2560_bbp_write(sc, RT2560_BBP_RX, rx);
! 2502: }
! 2503:
! 2504: const char *
! 2505: rt2560_get_rf(int rev)
! 2506: {
! 2507: switch (rev) {
! 2508: case RT2560_RF_2522: return "RT2522";
! 2509: case RT2560_RF_2523: return "RT2523";
! 2510: case RT2560_RF_2524: return "RT2524";
! 2511: case RT2560_RF_2525: return "RT2525";
! 2512: case RT2560_RF_2525E: return "RT2525e";
! 2513: case RT2560_RF_2526: return "RT2526";
! 2514: case RT2560_RF_5222: return "RT5222";
! 2515: default: return "unknown";
! 2516: }
! 2517: }
! 2518:
! 2519: void
! 2520: rt2560_read_eeprom(struct rt2560_softc *sc)
! 2521: {
! 2522: uint16_t val;
! 2523: int i;
! 2524:
! 2525: val = rt2560_eeprom_read(sc, RT2560_EEPROM_CONFIG0);
! 2526: sc->rf_rev = (val >> 11) & 0x1f;
! 2527: sc->hw_radio = (val >> 10) & 0x1;
! 2528: sc->led_mode = (val >> 6) & 0x7;
! 2529: sc->rx_ant = (val >> 4) & 0x3;
! 2530: sc->tx_ant = (val >> 2) & 0x3;
! 2531: sc->nb_ant = val & 0x3;
! 2532:
! 2533: /* read default values for BBP registers */
! 2534: for (i = 0; i < 16; i++) {
! 2535: val = rt2560_eeprom_read(sc, RT2560_EEPROM_BBP_BASE + i);
! 2536: sc->bbp_prom[i].reg = val >> 8;
! 2537: sc->bbp_prom[i].val = val & 0xff;
! 2538: }
! 2539:
! 2540: /* read Tx power for all b/g channels */
! 2541: for (i = 0; i < 14 / 2; i++) {
! 2542: val = rt2560_eeprom_read(sc, RT2560_EEPROM_TXPOWER + i);
! 2543: sc->txpow[i * 2] = val >> 8;
! 2544: sc->txpow[i * 2 + 1] = val & 0xff;
! 2545: }
! 2546: }
! 2547:
! 2548: int
! 2549: rt2560_bbp_init(struct rt2560_softc *sc)
! 2550: {
! 2551: #define N(a) (sizeof (a) / sizeof ((a)[0]))
! 2552: int i, ntries;
! 2553:
! 2554: /* wait for BBP to be ready */
! 2555: for (ntries = 0; ntries < 100; ntries++) {
! 2556: if (rt2560_bbp_read(sc, RT2560_BBP_VERSION) != 0)
! 2557: break;
! 2558: DELAY(1);
! 2559: }
! 2560: if (ntries == 100) {
! 2561: printf("%s: timeout waiting for BBP\n", sc->sc_dev.dv_xname);
! 2562: return EIO;
! 2563: }
! 2564:
! 2565: /* initialize BBP registers to default values */
! 2566: for (i = 0; i < N(rt2560_def_bbp); i++) {
! 2567: rt2560_bbp_write(sc, rt2560_def_bbp[i].reg,
! 2568: rt2560_def_bbp[i].val);
! 2569: }
! 2570: #if 0
! 2571: /* initialize BBP registers to values stored in EEPROM */
! 2572: for (i = 0; i < 16; i++) {
! 2573: if (sc->bbp_prom[i].reg == 0xff)
! 2574: continue;
! 2575: rt2560_bbp_write(sc, sc->bbp_prom[i].reg, sc->bbp_prom[i].val);
! 2576: }
! 2577: #endif
! 2578:
! 2579: return 0;
! 2580: #undef N
! 2581: }
! 2582:
! 2583: int
! 2584: rt2560_init(struct ifnet *ifp)
! 2585: {
! 2586: #define N(a) (sizeof (a) / sizeof ((a)[0]))
! 2587: struct rt2560_softc *sc = ifp->if_softc;
! 2588: struct ieee80211com *ic = &sc->sc_ic;
! 2589: uint32_t tmp;
! 2590: int i;
! 2591:
! 2592: /* for CardBus, power on the socket */
! 2593: if (!(sc->sc_flags & RT2560_ENABLED)) {
! 2594: if (sc->sc_enable != NULL && (*sc->sc_enable)(sc) != 0) {
! 2595: printf("%s: could not enable device\n",
! 2596: sc->sc_dev.dv_xname);
! 2597: return EIO;
! 2598: }
! 2599: sc->sc_flags |= RT2560_ENABLED;
! 2600: }
! 2601:
! 2602: rt2560_stop(ifp, 0);
! 2603:
! 2604: /* setup tx rings */
! 2605: tmp = RT2560_PRIO_RING_COUNT << 24 |
! 2606: RT2560_ATIM_RING_COUNT << 16 |
! 2607: RT2560_TX_RING_COUNT << 8 |
! 2608: RT2560_TX_DESC_SIZE;
! 2609:
! 2610: /* rings _must_ be initialized in this _exact_ order! */
! 2611: RAL_WRITE(sc, RT2560_TXCSR2, tmp);
! 2612: RAL_WRITE(sc, RT2560_TXCSR3, sc->txq.physaddr);
! 2613: RAL_WRITE(sc, RT2560_TXCSR5, sc->prioq.physaddr);
! 2614: RAL_WRITE(sc, RT2560_TXCSR4, sc->atimq.physaddr);
! 2615: RAL_WRITE(sc, RT2560_TXCSR6, sc->bcnq.physaddr);
! 2616:
! 2617: /* setup rx ring */
! 2618: tmp = RT2560_RX_RING_COUNT << 8 | RT2560_RX_DESC_SIZE;
! 2619:
! 2620: RAL_WRITE(sc, RT2560_RXCSR1, tmp);
! 2621: RAL_WRITE(sc, RT2560_RXCSR2, sc->rxq.physaddr);
! 2622:
! 2623: /* initialize MAC registers to default values */
! 2624: for (i = 0; i < N(rt2560_def_mac); i++)
! 2625: RAL_WRITE(sc, rt2560_def_mac[i].reg, rt2560_def_mac[i].val);
! 2626:
! 2627: IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));
! 2628: rt2560_set_macaddr(sc, ic->ic_myaddr);
! 2629:
! 2630: /* set basic rate set (will be updated later) */
! 2631: RAL_WRITE(sc, RT2560_ARSP_PLCP_1, 0x153);
! 2632:
! 2633: rt2560_set_txantenna(sc, 1);
! 2634: rt2560_set_rxantenna(sc, 1);
! 2635: rt2560_set_slottime(sc);
! 2636: rt2560_update_plcp(sc);
! 2637: rt2560_update_led(sc, 0, 0);
! 2638:
! 2639: RAL_WRITE(sc, RT2560_CSR1, RT2560_RESET_ASIC);
! 2640: RAL_WRITE(sc, RT2560_CSR1, RT2560_HOST_READY);
! 2641:
! 2642: if (rt2560_bbp_init(sc) != 0) {
! 2643: rt2560_stop(ifp, 1);
! 2644: return EIO;
! 2645: }
! 2646:
! 2647: /* set default BSS channel */
! 2648: ic->ic_bss->ni_chan = ic->ic_ibss_chan;
! 2649: rt2560_set_chan(sc, ic->ic_bss->ni_chan);
! 2650:
! 2651: /* kick Rx */
! 2652: tmp = RT2560_DROP_PHY_ERROR | RT2560_DROP_CRC_ERROR;
! 2653: if (ic->ic_opmode != IEEE80211_M_MONITOR) {
! 2654: tmp |= RT2560_DROP_CTL | RT2560_DROP_VERSION_ERROR;
! 2655: if (ic->ic_opmode != IEEE80211_M_HOSTAP)
! 2656: tmp |= RT2560_DROP_TODS;
! 2657: if (!(ifp->if_flags & IFF_PROMISC))
! 2658: tmp |= RT2560_DROP_NOT_TO_ME;
! 2659: }
! 2660: RAL_WRITE(sc, RT2560_RXCSR0, tmp);
! 2661:
! 2662: /* clear old FCS and Rx FIFO errors */
! 2663: RAL_READ(sc, RT2560_CNT0);
! 2664: RAL_READ(sc, RT2560_CNT4);
! 2665:
! 2666: /* clear any pending interrupts */
! 2667: RAL_WRITE(sc, RT2560_CSR7, 0xffffffff);
! 2668:
! 2669: /* enable interrupts */
! 2670: RAL_WRITE(sc, RT2560_CSR8, RT2560_INTR_MASK);
! 2671:
! 2672: ifp->if_flags &= ~IFF_OACTIVE;
! 2673: ifp->if_flags |= IFF_RUNNING;
! 2674:
! 2675: if (ic->ic_opmode == IEEE80211_M_MONITOR)
! 2676: ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
! 2677: else
! 2678: ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
! 2679:
! 2680: return 0;
! 2681: #undef N
! 2682: }
! 2683:
! 2684: void
! 2685: rt2560_stop(struct ifnet *ifp, int disable)
! 2686: {
! 2687: struct rt2560_softc *sc = ifp->if_softc;
! 2688: struct ieee80211com *ic = &sc->sc_ic;
! 2689:
! 2690: sc->sc_tx_timer = 0;
! 2691: ifp->if_timer = 0;
! 2692: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
! 2693:
! 2694: ieee80211_new_state(ic, IEEE80211_S_INIT, -1); /* free all nodes */
! 2695:
! 2696: /* abort Tx */
! 2697: RAL_WRITE(sc, RT2560_TXCSR0, RT2560_ABORT_TX);
! 2698:
! 2699: /* disable Rx */
! 2700: RAL_WRITE(sc, RT2560_RXCSR0, RT2560_DISABLE_RX);
! 2701:
! 2702: /* reset ASIC (and thus, BBP) */
! 2703: RAL_WRITE(sc, RT2560_CSR1, RT2560_RESET_ASIC);
! 2704: RAL_WRITE(sc, RT2560_CSR1, 0);
! 2705:
! 2706: /* disable interrupts */
! 2707: RAL_WRITE(sc, RT2560_CSR8, 0xffffffff);
! 2708:
! 2709: /* clear any pending interrupt */
! 2710: RAL_WRITE(sc, RT2560_CSR7, 0xffffffff);
! 2711:
! 2712: /* reset Tx and Rx rings */
! 2713: rt2560_reset_tx_ring(sc, &sc->txq);
! 2714: rt2560_reset_tx_ring(sc, &sc->atimq);
! 2715: rt2560_reset_tx_ring(sc, &sc->prioq);
! 2716: rt2560_reset_tx_ring(sc, &sc->bcnq);
! 2717: rt2560_reset_rx_ring(sc, &sc->rxq);
! 2718:
! 2719: /* for CardBus, power down the socket */
! 2720: if (disable && sc->sc_disable != NULL) {
! 2721: if (sc->sc_flags & RT2560_ENABLED) {
! 2722: (*sc->sc_disable)(sc);
! 2723: sc->sc_flags &= ~RT2560_ENABLED;
! 2724: }
! 2725: }
! 2726: }
! 2727:
! 2728: void
! 2729: rt2560_power(int why, void *arg)
! 2730: {
! 2731: struct rt2560_softc *sc = arg;
! 2732: struct ifnet *ifp = &sc->sc_ic.ic_if;
! 2733: int s;
! 2734:
! 2735: DPRINTF(("%s: rt2560_power(%d)\n", sc->sc_dev.dv_xname, why));
! 2736:
! 2737: s = splnet();
! 2738: switch (why) {
! 2739: case PWR_SUSPEND:
! 2740: case PWR_STANDBY:
! 2741: rt2560_stop(ifp, 1);
! 2742: if (sc->sc_power != NULL)
! 2743: (*sc->sc_power)(sc, why);
! 2744: break;
! 2745: case PWR_RESUME:
! 2746: if (ifp->if_flags & IFF_UP) {
! 2747: rt2560_init(ifp);
! 2748: if (sc->sc_power != NULL)
! 2749: (*sc->sc_power)(sc, why);
! 2750: if (ifp->if_flags & IFF_RUNNING)
! 2751: rt2560_start(ifp);
! 2752: }
! 2753: break;
! 2754: }
! 2755: splx(s);
! 2756: }
! 2757:
! 2758: void
! 2759: rt2560_shutdown(void *arg)
! 2760: {
! 2761: struct rt2560_softc *sc = arg;
! 2762:
! 2763: rt2560_stop(&sc->sc_ic.ic_if, 1);
! 2764: }
! 2765:
! 2766: struct cfdriver ral_cd = {
! 2767: NULL, "ral", DV_IFNET
! 2768: };
CVSweb