Annotation of sys/dev/ic/atw.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: atw.c,v 1.54 2007/07/18 18:22:26 damien Exp $ */
! 2: /* $NetBSD: atw.c,v 1.69 2004/07/23 07:07:55 dyoung Exp $ */
! 3:
! 4: /*-
! 5: * Copyright (c) 1998, 1999, 2000, 2002, 2003, 2004 The NetBSD Foundation, Inc.
! 6: * All rights reserved.
! 7: *
! 8: * This code is derived from software contributed to The NetBSD Foundation
! 9: * by David Young, by Jason R. Thorpe, and by Charles M. Hannum.
! 10: *
! 11: * Redistribution and use in source and binary forms, with or without
! 12: * modification, are permitted provided that the following conditions
! 13: * are met:
! 14: * 1. Redistributions of source code must retain the above copyright
! 15: * notice, this list of conditions and the following disclaimer.
! 16: * 2. Redistributions in binary form must reproduce the above copyright
! 17: * notice, this list of conditions and the following disclaimer in the
! 18: * documentation and/or other materials provided with the distribution.
! 19: * 3. All advertising materials mentioning features or use of this software
! 20: * must display the following acknowledgement:
! 21: * This product includes software developed by the NetBSD
! 22: * Foundation, Inc. and its contributors.
! 23: * 4. Neither the name of The NetBSD Foundation nor the names of its
! 24: * contributors may be used to endorse or promote products derived
! 25: * from this software without specific prior written permission.
! 26: *
! 27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
! 28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
! 31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 37: * POSSIBILITY OF SUCH DAMAGE.
! 38: */
! 39:
! 40: /*
! 41: * Device driver for the ADMtek ADM8211 802.11 MAC/BBP.
! 42: */
! 43:
! 44: #include <sys/cdefs.h>
! 45: #if defined(__NetBSD__)
! 46: __KERNEL_RCSID(0, "$NetBSD: atw.c,v 1.69 2004/07/23 07:07:55 dyoung Exp $");
! 47: #endif
! 48:
! 49: #include "bpfilter.h"
! 50:
! 51: #include <sys/param.h>
! 52: #include <sys/systm.h>
! 53: #include <sys/mbuf.h>
! 54: #include <sys/malloc.h>
! 55: #include <sys/kernel.h>
! 56: #include <sys/socket.h>
! 57: #include <sys/ioctl.h>
! 58: #include <sys/errno.h>
! 59: #include <sys/device.h>
! 60: #include <sys/time.h>
! 61:
! 62: #include <machine/endian.h>
! 63:
! 64: #include <uvm/uvm_extern.h>
! 65:
! 66: #include <net/if.h>
! 67: #include <net/if_dl.h>
! 68: #include <net/if_media.h>
! 69:
! 70: #if NBPFILTER > 0
! 71: #include <net/bpf.h>
! 72: #endif
! 73:
! 74: #ifdef INET
! 75: #include <netinet/in.h>
! 76: #include <netinet/if_ether.h>
! 77: #endif
! 78:
! 79: #include <net80211/ieee80211_var.h>
! 80: #include <net80211/ieee80211_radiotap.h>
! 81:
! 82: #include <machine/bus.h>
! 83: #include <machine/intr.h>
! 84:
! 85: #include <dev/ic/atwreg.h>
! 86: #include <dev/ic/rf3000reg.h>
! 87: #include <dev/ic/si4136reg.h>
! 88: #include <dev/ic/atwvar.h>
! 89: #include <dev/ic/smc93cx6var.h>
! 90:
! 91: /* XXX TBD open questions
! 92: *
! 93: *
! 94: * When should I set DSSS PAD in reg 0x15 of RF3000? In 1-2Mbps
! 95: * modes only, or all modes (5.5-11 Mbps CCK modes, too?) Does the MAC
! 96: * handle this for me?
! 97: *
! 98: */
! 99: /* device attachment
! 100: *
! 101: * print TOFS[012]
! 102: *
! 103: * device initialization
! 104: *
! 105: * clear ATW_FRCTL_MAXPSP to disable max power saving
! 106: * set ATW_TXBR_ALCUPDATE to enable ALC
! 107: * set TOFS[012]? (hope not)
! 108: * disable rx/tx
! 109: * set ATW_PAR_SWR (software reset)
! 110: * wait for ATW_PAR_SWR clear
! 111: * disable interrupts
! 112: * ack status register
! 113: * enable interrupts
! 114: *
! 115: * rx/tx initialization
! 116: *
! 117: * disable rx/tx w/ ATW_NAR_SR, ATW_NAR_ST
! 118: * allocate and init descriptor rings
! 119: * write ATW_PAR_DSL (descriptor skip length)
! 120: * write descriptor base addrs: ATW_TDBD, ATW_TDBP, write ATW_RDB
! 121: * write ATW_NAR_SQ for one/both transmit descriptor rings
! 122: * write ATW_NAR_SQ for one/both transmit descriptor rings
! 123: * enable rx/tx w/ ATW_NAR_SR, ATW_NAR_ST
! 124: *
! 125: * rx/tx end
! 126: *
! 127: * stop DMA
! 128: * disable rx/tx w/ ATW_NAR_SR, ATW_NAR_ST
! 129: * flush tx w/ ATW_NAR_HF
! 130: *
! 131: * scan
! 132: *
! 133: * initialize rx/tx
! 134: *
! 135: * BSS join: (re)association response
! 136: *
! 137: * set ATW_FRCTL_AID
! 138: *
! 139: * optimizations ???
! 140: *
! 141: */
! 142:
! 143: #define ATW_REFSLAVE /* slavishly do what the reference driver does */
! 144:
! 145: int atw_bbp_io_enable_delay = 20 * 1000;
! 146: int atw_bbp_io_disable_delay = 2 * 1000;
! 147: int atw_writewep_delay = 1000;
! 148: int atw_beacon_len_adjust = 4;
! 149: int atw_dwelltime = 200;
! 150: int atw_xindiv2 = 0;
! 151:
! 152: #ifdef ATW_DEBUG
! 153: int atw_debug = 0;
! 154:
! 155: #define ATW_DPRINTF(x) if (atw_debug > 0) printf x
! 156: #define ATW_DPRINTF2(x) if (atw_debug > 1) printf x
! 157: #define ATW_DPRINTF3(x) if (atw_debug > 2) printf x
! 158: #define DPRINTF(sc, x) if ((sc)->sc_ic.ic_if.if_flags & IFF_DEBUG) printf x
! 159: #define DPRINTF2(sc, x) if ((sc)->sc_ic.ic_if.if_flags & IFF_DEBUG) ATW_DPRINTF2(x)
! 160: #define DPRINTF3(sc, x) if ((sc)->sc_ic.ic_if.if_flags & IFF_DEBUG) ATW_DPRINTF3(x)
! 161: void atw_print_regs(struct atw_softc *, const char *);
! 162: void atw_dump_pkt(struct ifnet *, struct mbuf *);
! 163:
! 164: /* Note well: I never got atw_rf3000_read or atw_si4126_read to work. */
! 165: # ifdef ATW_BBPDEBUG
! 166: int atw_rf3000_read(struct atw_softc *sc, u_int, u_int *);
! 167: void atw_rf3000_print(struct atw_softc *);
! 168: # endif /* ATW_BBPDEBUG */
! 169:
! 170: # ifdef ATW_SYNDEBUG
! 171: int atw_si4126_read(struct atw_softc *, u_int, u_int *);
! 172: void atw_si4126_print(struct atw_softc *);
! 173: # endif /* ATW_SYNDEBUG */
! 174:
! 175: #else
! 176: #define ATW_DPRINTF(x)
! 177: #define ATW_DPRINTF2(x)
! 178: #define ATW_DPRINTF3(x)
! 179: #define DPRINTF(sc, x) /* nothing */
! 180: #define DPRINTF2(sc, x) /* nothing */
! 181: #define DPRINTF3(sc, x) /* nothing */
! 182: #endif
! 183:
! 184: #ifdef ATW_STATS
! 185: void atw_print_stats(struct atw_softc *);
! 186: #endif
! 187:
! 188: const char *atw_printmac(u_int8_t);
! 189:
! 190: /* ifnet methods */
! 191: void atw_start(struct ifnet *);
! 192: void atw_watchdog(struct ifnet *);
! 193: int atw_ioctl(struct ifnet *, u_long, caddr_t);
! 194: int atw_init(struct ifnet *);
! 195: void atw_stop(struct ifnet *, int);
! 196:
! 197: /* Rx/Tx process */
! 198: void atw_rxdrain(struct atw_softc *);
! 199: void atw_txdrain(struct atw_softc *);
! 200: int atw_add_rxbuf(struct atw_softc *, int);
! 201: void atw_idle(struct atw_softc *, u_int32_t);
! 202:
! 203: /* Device (de)activation and power state */
! 204: void atw_disable(struct atw_softc *);
! 205: void atw_reset(struct atw_softc *);
! 206:
! 207: /* Interrupt handlers */
! 208: void atw_rxintr(struct atw_softc *);
! 209: void atw_txintr(struct atw_softc *);
! 210: void atw_linkintr(struct atw_softc *, u_int32_t);
! 211:
! 212: /* 802.11 state machine */
! 213: int atw_newstate(struct ieee80211com *, enum ieee80211_state, int);
! 214: int atw_tune(struct atw_softc *);
! 215: void atw_recv_mgmt(struct ieee80211com *, struct mbuf *,
! 216: struct ieee80211_node *, int, int, u_int32_t);
! 217: void atw_next_scan(void *);
! 218:
! 219: /* Device initialization */
! 220: void atw_wcsr_init(struct atw_softc *);
! 221: void atw_cmdr_init(struct atw_softc *);
! 222: void atw_tofs2_init(struct atw_softc *);
! 223: void atw_txlmt_init(struct atw_softc *);
! 224: void atw_test1_init(struct atw_softc *);
! 225: void atw_rf_reset(struct atw_softc *);
! 226: void atw_cfp_init(struct atw_softc *);
! 227: void atw_tofs0_init(struct atw_softc *);
! 228: void atw_ifs_init(struct atw_softc *);
! 229: void atw_response_times_init(struct atw_softc *);
! 230: void atw_bbp_io_init(struct atw_softc *);
! 231: void atw_nar_init(struct atw_softc *);
! 232:
! 233: /* RAM/ROM utilities */
! 234: void atw_clear_sram(struct atw_softc *);
! 235: void atw_write_sram(struct atw_softc *, u_int, u_int8_t *, u_int);
! 236: int atw_read_srom(struct atw_softc *);
! 237:
! 238: /* BSS setup */
! 239: void atw_predict_beacon(struct atw_softc *sc);
! 240: void atw_start_beacon(struct atw_softc *, int);
! 241: void atw_write_bssid(struct atw_softc *);
! 242: void atw_write_ssid(struct atw_softc *);
! 243: void atw_write_sup_rates(struct atw_softc *);
! 244: void atw_write_wep(struct atw_softc *);
! 245:
! 246: /* Media */
! 247: int atw_media_change(struct ifnet *);
! 248: void atw_media_status(struct ifnet *, struct ifmediareq *);
! 249:
! 250: void atw_filter_setup(struct atw_softc *);
! 251:
! 252: /* 802.11 utilities */
! 253: struct ieee80211_node *atw_node_alloc(struct ieee80211com *);
! 254: void atw_node_free(struct ieee80211com *, struct ieee80211_node *);
! 255: static __inline uint32_t atw_last_even_tsft(uint32_t, uint32_t, uint32_t);
! 256: uint64_t atw_get_tsft(struct atw_softc *sc);
! 257: void atw_change_ibss(struct atw_softc *);
! 258: int atw_compute_duration1(int, int, uint32_t, int, struct atw_duration *);
! 259: int atw_compute_duration(struct ieee80211_frame *, int, uint32_t, int,
! 260: int, struct atw_duration *, struct atw_duration *, int *, int);
! 261:
! 262: /*
! 263: * Tuner/transceiver/modem
! 264: */
! 265: void atw_bbp_io_enable(struct atw_softc *, int);
! 266:
! 267: /* RFMD RF3000 Baseband Processor */
! 268: int atw_rf3000_init(struct atw_softc *);
! 269: int atw_rf3000_tune(struct atw_softc *, u_int);
! 270: int atw_rf3000_write(struct atw_softc *, u_int, u_int);
! 271:
! 272: /* Silicon Laboratories Si4126 RF/IF Synthesizer */
! 273: void atw_si4126_tune(struct atw_softc *, u_int);
! 274: void atw_si4126_write(struct atw_softc *, u_int, u_int);
! 275: void atw_si4126_init(struct atw_softc *);
! 276:
! 277: const struct atw_txthresh_tab atw_txthresh_tab_lo[] = ATW_TXTHRESH_TAB_LO_RATE;
! 278: const struct atw_txthresh_tab atw_txthresh_tab_hi[] = ATW_TXTHRESH_TAB_HI_RATE;
! 279:
! 280: struct cfdriver atw_cd = {
! 281: NULL, "atw", DV_IFNET
! 282: };
! 283:
! 284: static const u_int atw_rfmd2958_ifn[] = {
! 285: 0x22bd, 0x22d2, 0x22e8, 0x22fe, 0x2314, 0x232a, 0x2340,
! 286: 0x2355, 0x236b, 0x2381, 0x2397, 0x23ad, 0x23c2, 0x23f7
! 287: };
! 288:
! 289: static const u_int atw_rfmd2958_rf1r[] = {
! 290: 0x05d17, 0x3a2e8, 0x2e8ba, 0x22e8b, 0x1745d, 0x0ba2e, 0x00000,
! 291: 0x345d1, 0x28ba2, 0x1d174, 0x11745, 0x05d17, 0x3a2e8, 0x11745
! 292: };
! 293:
! 294:
! 295: #ifdef ATW_DEBUG
! 296:
! 297: const char *atw_tx_state[] = {
! 298: "STOPPED",
! 299: "RUNNING - read descriptor",
! 300: "RUNNING - transmitting",
! 301: "RUNNING - filling fifo", /* XXX */
! 302: "SUSPENDED",
! 303: "RUNNING -- write descriptor",
! 304: "RUNNING -- write last descriptor",
! 305: "RUNNING - fifo full"
! 306: };
! 307:
! 308: const char *atw_rx_state[] = {
! 309: "STOPPED",
! 310: "RUNNING - read descriptor",
! 311: "RUNNING - check this packet, pre-fetch next",
! 312: "RUNNING - wait for reception",
! 313: "SUSPENDED",
! 314: "RUNNING - write descriptor",
! 315: "RUNNING - flush fifo",
! 316: "RUNNING - fifo drain"
! 317: };
! 318:
! 319: #endif
! 320:
! 321: #ifndef __OpenBSD__
! 322: int
! 323: atw_activate(struct device *self, enum devact act)
! 324: {
! 325: struct atw_softc *sc = (struct atw_softc *)self;
! 326: int rv = 0, s;
! 327:
! 328: s = splnet();
! 329: switch (act) {
! 330: case DVACT_ACTIVATE:
! 331: break;
! 332:
! 333: case DVACT_DEACTIVATE:
! 334: if_deactivate(&sc->sc_ic.ic_if);
! 335: break;
! 336: }
! 337: splx(s);
! 338: return rv;
! 339: }
! 340: #endif
! 341:
! 342: /*
! 343: * atw_enable:
! 344: *
! 345: * Enable the ADM8211 chip.
! 346: */
! 347: int
! 348: atw_enable(struct atw_softc *sc)
! 349: {
! 350:
! 351: if (ATW_IS_ENABLED(sc) == 0) {
! 352: if (sc->sc_enable != NULL && (*sc->sc_enable)(sc) != 0) {
! 353: printf("%s: device enable failed\n",
! 354: sc->sc_dev.dv_xname);
! 355: return (EIO);
! 356: }
! 357: sc->sc_flags |= ATWF_ENABLED;
! 358: }
! 359: return (0);
! 360: }
! 361:
! 362: /*
! 363: * atw_disable:
! 364: *
! 365: * Disable the ADM8211 chip.
! 366: */
! 367: void
! 368: atw_disable(struct atw_softc *sc)
! 369: {
! 370: if (!ATW_IS_ENABLED(sc))
! 371: return;
! 372: if (sc->sc_disable != NULL)
! 373: (*sc->sc_disable)(sc);
! 374: sc->sc_flags &= ~ATWF_ENABLED;
! 375: }
! 376:
! 377: /* Returns -1 on failure. */
! 378: int
! 379: atw_read_srom(struct atw_softc *sc)
! 380: {
! 381: struct seeprom_descriptor sd;
! 382: u_int32_t test0, fail_bits;
! 383:
! 384: (void)memset(&sd, 0, sizeof(sd));
! 385:
! 386: test0 = ATW_READ(sc, ATW_TEST0);
! 387:
! 388: switch (sc->sc_rev) {
! 389: case ATW_REVISION_BA:
! 390: case ATW_REVISION_CA:
! 391: fail_bits = ATW_TEST0_EPNE;
! 392: break;
! 393: default:
! 394: fail_bits = ATW_TEST0_EPNE|ATW_TEST0_EPSNM;
! 395: break;
! 396: }
! 397: if ((test0 & fail_bits) != 0) {
! 398: printf("%s: bad or missing/bad SROM\n", sc->sc_dev.dv_xname);
! 399: return -1;
! 400: }
! 401:
! 402: switch (test0 & ATW_TEST0_EPTYP_MASK) {
! 403: case ATW_TEST0_EPTYP_93c66:
! 404: ATW_DPRINTF(("%s: 93c66 SROM\n", sc->sc_dev.dv_xname));
! 405: sc->sc_sromsz = 512;
! 406: sd.sd_chip = C56_66;
! 407: break;
! 408: case ATW_TEST0_EPTYP_93c46:
! 409: ATW_DPRINTF(("%s: 93c46 SROM\n", sc->sc_dev.dv_xname));
! 410: sc->sc_sromsz = 128;
! 411: sd.sd_chip = C46;
! 412: break;
! 413: default:
! 414: printf("%s: unknown SROM type %d\n", sc->sc_dev.dv_xname,
! 415: MASK_AND_RSHIFT(test0, ATW_TEST0_EPTYP_MASK));
! 416: return -1;
! 417: }
! 418:
! 419: sc->sc_srom = malloc(sc->sc_sromsz, M_DEVBUF, M_NOWAIT);
! 420: if (sc->sc_srom == NULL) {
! 421: printf("%s: unable to allocate SROM buffer\n",
! 422: sc->sc_dev.dv_xname);
! 423: return -1;
! 424: }
! 425:
! 426: (void)memset(sc->sc_srom, 0, sc->sc_sromsz);
! 427: /* ADM8211 has a single 32-bit register for controlling the
! 428: * 93cx6 SROM. Bit SRS enables the serial port. There is no
! 429: * "ready" bit. The ADM8211 input/output sense is the reverse
! 430: * of read_seeprom's.
! 431: */
! 432: sd.sd_tag = sc->sc_st;
! 433: sd.sd_bsh = sc->sc_sh;
! 434: sd.sd_regsize = 4;
! 435: sd.sd_control_offset = ATW_SPR;
! 436: sd.sd_status_offset = ATW_SPR;
! 437: sd.sd_dataout_offset = ATW_SPR;
! 438: sd.sd_CK = ATW_SPR_SCLK;
! 439: sd.sd_CS = ATW_SPR_SCS;
! 440: sd.sd_DI = ATW_SPR_SDO;
! 441: sd.sd_DO = ATW_SPR_SDI;
! 442: sd.sd_MS = ATW_SPR_SRS;
! 443: sd.sd_RDY = 0;
! 444:
! 445: if (!read_seeprom(&sd, sc->sc_srom, 0, sc->sc_sromsz/2)) {
! 446: printf("%s: could not read SROM\n", sc->sc_dev.dv_xname);
! 447: free(sc->sc_srom, M_DEVBUF);
! 448: return -1;
! 449: }
! 450: #ifdef ATW_DEBUG
! 451: {
! 452: int i;
! 453: ATW_DPRINTF(("\nSerial EEPROM:\n\t"));
! 454: for (i = 0; i < sc->sc_sromsz/2; i = i + 1) {
! 455: if (((i % 8) == 0) && (i != 0)) {
! 456: ATW_DPRINTF(("\n\t"));
! 457: }
! 458: ATW_DPRINTF((" 0x%x", sc->sc_srom[i]));
! 459: }
! 460: ATW_DPRINTF(("\n"));
! 461: }
! 462: #endif /* ATW_DEBUG */
! 463: return 0;
! 464: }
! 465:
! 466: #ifdef ATW_DEBUG
! 467: void
! 468: atw_print_regs(struct atw_softc *sc, const char *where)
! 469: {
! 470: #define PRINTREG(sc, reg) \
! 471: ATW_DPRINTF2(("%s: reg[ " #reg " / %03x ] = %08x\n", \
! 472: sc->sc_dev.dv_xname, reg, ATW_READ(sc, reg)))
! 473:
! 474: ATW_DPRINTF2(("%s: %s\n", sc->sc_dev.dv_xname, where));
! 475:
! 476: PRINTREG(sc, ATW_PAR);
! 477: PRINTREG(sc, ATW_FRCTL);
! 478: PRINTREG(sc, ATW_TDR);
! 479: PRINTREG(sc, ATW_WTDP);
! 480: PRINTREG(sc, ATW_RDR);
! 481: PRINTREG(sc, ATW_WRDP);
! 482: PRINTREG(sc, ATW_RDB);
! 483: PRINTREG(sc, ATW_CSR3A);
! 484: PRINTREG(sc, ATW_TDBD);
! 485: PRINTREG(sc, ATW_TDBP);
! 486: PRINTREG(sc, ATW_STSR);
! 487: PRINTREG(sc, ATW_CSR5A);
! 488: PRINTREG(sc, ATW_NAR);
! 489: PRINTREG(sc, ATW_CSR6A);
! 490: PRINTREG(sc, ATW_IER);
! 491: PRINTREG(sc, ATW_CSR7A);
! 492: PRINTREG(sc, ATW_LPC);
! 493: PRINTREG(sc, ATW_TEST1);
! 494: PRINTREG(sc, ATW_SPR);
! 495: PRINTREG(sc, ATW_TEST0);
! 496: PRINTREG(sc, ATW_WCSR);
! 497: PRINTREG(sc, ATW_WPDR);
! 498: PRINTREG(sc, ATW_GPTMR);
! 499: PRINTREG(sc, ATW_GPIO);
! 500: PRINTREG(sc, ATW_BBPCTL);
! 501: PRINTREG(sc, ATW_SYNCTL);
! 502: PRINTREG(sc, ATW_PLCPHD);
! 503: PRINTREG(sc, ATW_MMIWADDR);
! 504: PRINTREG(sc, ATW_MMIRADDR1);
! 505: PRINTREG(sc, ATW_MMIRADDR2);
! 506: PRINTREG(sc, ATW_TXBR);
! 507: PRINTREG(sc, ATW_CSR15A);
! 508: PRINTREG(sc, ATW_ALCSTAT);
! 509: PRINTREG(sc, ATW_TOFS2);
! 510: PRINTREG(sc, ATW_CMDR);
! 511: PRINTREG(sc, ATW_PCIC);
! 512: PRINTREG(sc, ATW_PMCSR);
! 513: PRINTREG(sc, ATW_PAR0);
! 514: PRINTREG(sc, ATW_PAR1);
! 515: PRINTREG(sc, ATW_MAR0);
! 516: PRINTREG(sc, ATW_MAR1);
! 517: PRINTREG(sc, ATW_ATIMDA0);
! 518: PRINTREG(sc, ATW_ABDA1);
! 519: PRINTREG(sc, ATW_BSSID0);
! 520: PRINTREG(sc, ATW_TXLMT);
! 521: PRINTREG(sc, ATW_MIBCNT);
! 522: PRINTREG(sc, ATW_BCNT);
! 523: PRINTREG(sc, ATW_TSFTH);
! 524: PRINTREG(sc, ATW_TSC);
! 525: PRINTREG(sc, ATW_SYNRF);
! 526: PRINTREG(sc, ATW_BPLI);
! 527: PRINTREG(sc, ATW_CAP0);
! 528: PRINTREG(sc, ATW_CAP1);
! 529: PRINTREG(sc, ATW_RMD);
! 530: PRINTREG(sc, ATW_CFPP);
! 531: PRINTREG(sc, ATW_TOFS0);
! 532: PRINTREG(sc, ATW_TOFS1);
! 533: PRINTREG(sc, ATW_IFST);
! 534: PRINTREG(sc, ATW_RSPT);
! 535: PRINTREG(sc, ATW_TSFTL);
! 536: PRINTREG(sc, ATW_WEPCTL);
! 537: PRINTREG(sc, ATW_WESK);
! 538: PRINTREG(sc, ATW_WEPCNT);
! 539: PRINTREG(sc, ATW_MACTEST);
! 540: PRINTREG(sc, ATW_FER);
! 541: PRINTREG(sc, ATW_FEMR);
! 542: PRINTREG(sc, ATW_FPSR);
! 543: PRINTREG(sc, ATW_FFER);
! 544: #undef PRINTREG
! 545: }
! 546: #endif /* ATW_DEBUG */
! 547:
! 548: const char*
! 549: atw_printmac(u_int8_t rev) {
! 550: switch (rev) {
! 551: case ATW_REVISION_AB:
! 552: return "ADM8211AB";
! 553: case ATW_REVISION_AF:
! 554: return "ADM8211AF";
! 555: case ATW_REVISION_BA:
! 556: return "ADM8211BA";
! 557: case ATW_REVISION_CA:
! 558: return "ADM8211CA";
! 559: default:
! 560: return "unknown";
! 561: }
! 562: }
! 563:
! 564: /*
! 565: * Finish attaching an ADMtek ADM8211 MAC. Called by bus-specific front-end.
! 566: */
! 567: void
! 568: atw_attach(struct atw_softc *sc)
! 569: {
! 570: static const u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = {
! 571: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
! 572: };
! 573: struct ieee80211com *ic = &sc->sc_ic;
! 574: struct ifnet *ifp = &ic->ic_if;
! 575: int country_code, error, i, srom_major;
! 576: u_int32_t reg;
! 577: static const char *type_strings[] = {"Intersil (not supported)",
! 578: "RFMD", "Marvel (not supported)"};
! 579:
! 580: sc->sc_txth = atw_txthresh_tab_lo;
! 581:
! 582: SIMPLEQ_INIT(&sc->sc_txfreeq);
! 583: SIMPLEQ_INIT(&sc->sc_txdirtyq);
! 584:
! 585: #ifdef ATW_DEBUG
! 586: atw_print_regs(sc, "atw_attach");
! 587: #endif /* ATW_DEBUG */
! 588:
! 589: /*
! 590: * Allocate the control data structures, and create and load the
! 591: * DMA map for it.
! 592: */
! 593: if ((error = bus_dmamem_alloc(sc->sc_dmat,
! 594: sizeof(struct atw_control_data), PAGE_SIZE, 0, &sc->sc_cdseg,
! 595: 1, &sc->sc_cdnseg, 0)) != 0) {
! 596: printf("%s: unable to allocate control data, error = %d\n",
! 597: sc->sc_dev.dv_xname, error);
! 598: goto fail_0;
! 599: }
! 600:
! 601: if ((error = bus_dmamem_map(sc->sc_dmat, &sc->sc_cdseg, sc->sc_cdnseg,
! 602: sizeof(struct atw_control_data), (caddr_t *)&sc->sc_control_data,
! 603: BUS_DMA_COHERENT)) != 0) {
! 604: printf("%s: unable to map control data, error = %d\n",
! 605: sc->sc_dev.dv_xname, error);
! 606: goto fail_1;
! 607: }
! 608:
! 609: if ((error = bus_dmamap_create(sc->sc_dmat,
! 610: sizeof(struct atw_control_data), 1,
! 611: sizeof(struct atw_control_data), 0, 0, &sc->sc_cddmamap)) != 0) {
! 612: printf("%s: unable to create control data DMA map, "
! 613: "error = %d\n", sc->sc_dev.dv_xname, error);
! 614: goto fail_2;
! 615: }
! 616:
! 617: if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap,
! 618: sc->sc_control_data, sizeof(struct atw_control_data), NULL,
! 619: 0)) != 0) {
! 620: printf("%s: unable to load control data DMA map, error = %d\n",
! 621: sc->sc_dev.dv_xname, error);
! 622: goto fail_3;
! 623: }
! 624:
! 625: /*
! 626: * Create the transmit buffer DMA maps.
! 627: */
! 628: sc->sc_ntxsegs = ATW_NTXSEGS;
! 629: for (i = 0; i < ATW_TXQUEUELEN; i++) {
! 630: if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
! 631: sc->sc_ntxsegs, MCLBYTES, 0, 0,
! 632: &sc->sc_txsoft[i].txs_dmamap)) != 0) {
! 633: printf("%s: unable to create tx DMA map %d, "
! 634: "error = %d\n", sc->sc_dev.dv_xname, i, error);
! 635: goto fail_4;
! 636: }
! 637: }
! 638:
! 639: /*
! 640: * Create the receive buffer DMA maps.
! 641: */
! 642: for (i = 0; i < ATW_NRXDESC; i++) {
! 643: if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
! 644: MCLBYTES, 0, 0, &sc->sc_rxsoft[i].rxs_dmamap)) != 0) {
! 645: printf("%s: unable to create rx DMA map %d, "
! 646: "error = %d\n", sc->sc_dev.dv_xname, i, error);
! 647: goto fail_5;
! 648: }
! 649: }
! 650: for (i = 0; i < ATW_NRXDESC; i++) {
! 651: sc->sc_rxsoft[i].rxs_mbuf = NULL;
! 652: }
! 653:
! 654: switch (sc->sc_rev) {
! 655: case ATW_REVISION_AB:
! 656: case ATW_REVISION_AF:
! 657: sc->sc_sramlen = ATW_SRAM_A_SIZE;
! 658: break;
! 659: case ATW_REVISION_BA:
! 660: case ATW_REVISION_CA:
! 661: sc->sc_sramlen = ATW_SRAM_B_SIZE;
! 662: break;
! 663: }
! 664:
! 665: /* Reset the chip to a known state. */
! 666: atw_reset(sc);
! 667:
! 668: if (atw_read_srom(sc) == -1)
! 669: return;
! 670:
! 671: sc->sc_rftype = MASK_AND_RSHIFT(sc->sc_srom[ATW_SR_CSR20],
! 672: ATW_SR_RFTYPE_MASK);
! 673:
! 674: sc->sc_bbptype = MASK_AND_RSHIFT(sc->sc_srom[ATW_SR_CSR20],
! 675: ATW_SR_BBPTYPE_MASK);
! 676:
! 677: if (sc->sc_rftype >= sizeof(type_strings)/sizeof(type_strings[0])) {
! 678: printf("%s: unknown RF\n", sc->sc_dev.dv_xname);
! 679: return;
! 680: }
! 681: if (sc->sc_bbptype >= sizeof(type_strings)/sizeof(type_strings[0])) {
! 682: printf("%s: unknown BBP\n", sc->sc_dev.dv_xname);
! 683: return;
! 684: }
! 685:
! 686: printf("%s: MAC %s, BBP %s, RF %s", sc->sc_dev.dv_xname,
! 687: atw_printmac(sc->sc_rev), type_strings[sc->sc_bbptype],
! 688: type_strings[sc->sc_rftype]);
! 689:
! 690: /* XXX There exists a Linux driver which seems to use RFType = 0 for
! 691: * MARVEL. My bug, or theirs?
! 692: */
! 693:
! 694: reg = LSHIFT(sc->sc_rftype, ATW_SYNCTL_RFTYPE_MASK);
! 695:
! 696: switch (sc->sc_rftype) {
! 697: case ATW_RFTYPE_INTERSIL:
! 698: reg |= ATW_SYNCTL_CS1;
! 699: break;
! 700: case ATW_RFTYPE_RFMD:
! 701: reg |= ATW_SYNCTL_CS0;
! 702: break;
! 703: case ATW_RFTYPE_MARVEL:
! 704: break;
! 705: }
! 706:
! 707: sc->sc_synctl_rd = reg | ATW_SYNCTL_RD;
! 708: sc->sc_synctl_wr = reg | ATW_SYNCTL_WR;
! 709:
! 710: reg = LSHIFT(sc->sc_bbptype, ATW_BBPCTL_TYPE_MASK);
! 711:
! 712: switch (sc->sc_bbptype) {
! 713: case ATW_BBPTYPE_INTERSIL:
! 714: reg |= ATW_BBPCTL_TWI;
! 715: break;
! 716: case ATW_BBPTYPE_RFMD:
! 717: reg |= ATW_BBPCTL_RF3KADDR_ADDR | ATW_BBPCTL_NEGEDGE_DO |
! 718: ATW_BBPCTL_CCA_ACTLO;
! 719: break;
! 720: case ATW_BBPTYPE_MARVEL:
! 721: break;
! 722: case ATW_C_BBPTYPE_RFMD:
! 723: printf("%s: ADM8211C MAC/RFMD BBP not supported yet.\n",
! 724: sc->sc_dev.dv_xname);
! 725: break;
! 726: }
! 727:
! 728: sc->sc_bbpctl_wr = reg | ATW_BBPCTL_WR;
! 729: sc->sc_bbpctl_rd = reg | ATW_BBPCTL_RD;
! 730:
! 731: /*
! 732: * From this point forward, the attachment cannot fail. A failure
! 733: * before this point releases all resources that may have been
! 734: * allocated.
! 735: */
! 736: sc->sc_flags |= ATWF_ATTACHED /* | ATWF_RTSCTS */;
! 737:
! 738: ATW_DPRINTF((" SROM MAC %04x%04x%04x",
! 739: htole16(sc->sc_srom[ATW_SR_MAC00]),
! 740: htole16(sc->sc_srom[ATW_SR_MAC01]),
! 741: htole16(sc->sc_srom[ATW_SR_MAC10])));
! 742:
! 743: srom_major = MASK_AND_RSHIFT(sc->sc_srom[ATW_SR_FORMAT_VERSION],
! 744: ATW_SR_MAJOR_MASK);
! 745:
! 746: if (srom_major < 2)
! 747: sc->sc_rf3000_options1 = 0;
! 748: else if (sc->sc_rev == ATW_REVISION_BA) {
! 749: sc->sc_rf3000_options1 =
! 750: MASK_AND_RSHIFT(sc->sc_srom[ATW_SR_CR28_CR03],
! 751: ATW_SR_CR28_MASK);
! 752: } else
! 753: sc->sc_rf3000_options1 = 0;
! 754:
! 755: sc->sc_rf3000_options2 = MASK_AND_RSHIFT(sc->sc_srom[ATW_SR_CTRY_CR29],
! 756: ATW_SR_CR29_MASK);
! 757:
! 758: country_code = MASK_AND_RSHIFT(sc->sc_srom[ATW_SR_CTRY_CR29],
! 759: ATW_SR_CTRY_MASK);
! 760:
! 761: #define ADD_CHANNEL(_ic, _chan) do { \
! 762: _ic->ic_channels[_chan].ic_flags = IEEE80211_CHAN_B; \
! 763: _ic->ic_channels[_chan].ic_freq = \
! 764: ieee80211_ieee2mhz(_chan, _ic->ic_channels[_chan].ic_flags);\
! 765: } while (0)
! 766:
! 767: /* Find available channels */
! 768: switch (country_code) {
! 769: case COUNTRY_MMK2: /* 1-14 */
! 770: ADD_CHANNEL(ic, 14);
! 771: /*FALLTHROUGH*/
! 772: case COUNTRY_ETSI: /* 1-13 */
! 773: for (i = 1; i <= 13; i++)
! 774: ADD_CHANNEL(ic, i);
! 775: break;
! 776: case COUNTRY_FCC: /* 1-11 */
! 777: case COUNTRY_IC: /* 1-11 */
! 778: for (i = 1; i <= 11; i++)
! 779: ADD_CHANNEL(ic, i);
! 780: break;
! 781: case COUNTRY_MMK: /* 14 */
! 782: ADD_CHANNEL(ic, 14);
! 783: break;
! 784: case COUNTRY_FRANCE: /* 10-13 */
! 785: for (i = 10; i <= 13; i++)
! 786: ADD_CHANNEL(ic, i);
! 787: break;
! 788: default: /* assume channels 10-11 */
! 789: case COUNTRY_SPAIN: /* 10-11 */
! 790: for (i = 10; i <= 11; i++)
! 791: ADD_CHANNEL(ic, i);
! 792: break;
! 793: }
! 794:
! 795: /* Read the MAC address. */
! 796: reg = ATW_READ(sc, ATW_PAR0);
! 797: ic->ic_myaddr[0] = MASK_AND_RSHIFT(reg, ATW_PAR0_PAB0_MASK);
! 798: ic->ic_myaddr[1] = MASK_AND_RSHIFT(reg, ATW_PAR0_PAB1_MASK);
! 799: ic->ic_myaddr[2] = MASK_AND_RSHIFT(reg, ATW_PAR0_PAB2_MASK);
! 800: ic->ic_myaddr[3] = MASK_AND_RSHIFT(reg, ATW_PAR0_PAB3_MASK);
! 801: reg = ATW_READ(sc, ATW_PAR1);
! 802: ic->ic_myaddr[4] = MASK_AND_RSHIFT(reg, ATW_PAR1_PAB4_MASK);
! 803: ic->ic_myaddr[5] = MASK_AND_RSHIFT(reg, ATW_PAR1_PAB5_MASK);
! 804:
! 805: if (IEEE80211_ADDR_EQ(ic->ic_myaddr, empty_macaddr)) {
! 806: printf(" could not get mac address, attach failed\n");
! 807: return;
! 808: }
! 809:
! 810: printf(", address %s\n", ether_sprintf(ic->ic_myaddr));
! 811:
! 812: memcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
! 813: ifp->if_softc = sc;
! 814: ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST |
! 815: IFF_NOTRAILERS;
! 816: ifp->if_ioctl = atw_ioctl;
! 817: ifp->if_start = atw_start;
! 818: ifp->if_watchdog = atw_watchdog;
! 819: #if !defined(__OpenBSD__)
! 820: ifp->if_init = atw_init;
! 821: ifp->if_stop = atw_stop;
! 822: #endif
! 823: IFQ_SET_READY(&ifp->if_snd);
! 824:
! 825: ic->ic_phytype = IEEE80211_T_DS;
! 826: ic->ic_opmode = IEEE80211_M_STA;
! 827: ic->ic_caps = IEEE80211_C_PMGT | IEEE80211_C_IBSS |
! 828: IEEE80211_C_HOSTAP | IEEE80211_C_MONITOR | IEEE80211_C_WEP;
! 829:
! 830: ic->ic_sup_rates[IEEE80211_MODE_11B] = ieee80211_std_rateset_11b;
! 831:
! 832: /*
! 833: * Call MI attach routines.
! 834: */
! 835:
! 836: if_attach(ifp);
! 837: ieee80211_ifattach(ifp);
! 838:
! 839: sc->sc_newstate = ic->ic_newstate;
! 840: ic->ic_newstate = atw_newstate;
! 841:
! 842: sc->sc_recv_mgmt = ic->ic_recv_mgmt;
! 843: ic->ic_recv_mgmt = atw_recv_mgmt;
! 844:
! 845: sc->sc_node_free = ic->ic_node_free;
! 846: ic->ic_node_free = atw_node_free;
! 847:
! 848: sc->sc_node_alloc = ic->ic_node_alloc;
! 849: ic->ic_node_alloc = atw_node_alloc;
! 850:
! 851: /* possibly we should fill in our own sc_send_prresp, since
! 852: * the ADM8211 is probably sending probe responses in ad hoc
! 853: * mode.
! 854: */
! 855:
! 856: /* complete initialization */
! 857: ieee80211_media_init(ifp, atw_media_change, atw_media_status);
! 858: timeout_set(&sc->sc_scan_to, atw_next_scan, sc);
! 859:
! 860: #if NBPFILTER > 0
! 861: bpfattach(&sc->sc_radiobpf, ifp, DLT_IEEE802_11_RADIO,
! 862: sizeof(struct ieee80211_frame) + 64);
! 863: #endif
! 864:
! 865: /*
! 866: * Make sure the interface is shutdown during reboot.
! 867: */
! 868: sc->sc_sdhook = shutdownhook_establish(atw_shutdown, sc);
! 869: if (sc->sc_sdhook == NULL)
! 870: printf("%s: WARNING: unable to establish shutdown hook\n",
! 871: sc->sc_dev.dv_xname);
! 872:
! 873: /*
! 874: * Add a suspend hook to make sure we come back up after a
! 875: * resume.
! 876: */
! 877: sc->sc_powerhook = powerhook_establish(atw_power, sc);
! 878: if (sc->sc_powerhook == NULL)
! 879: printf("%s: WARNING: unable to establish power hook\n",
! 880: sc->sc_dev.dv_xname);
! 881:
! 882: memset(&sc->sc_rxtapu, 0, sizeof(sc->sc_rxtapu));
! 883: sc->sc_rxtap.ar_ihdr.it_len = sizeof(sc->sc_rxtapu);
! 884: sc->sc_rxtap.ar_ihdr.it_present = ATW_RX_RADIOTAP_PRESENT;
! 885:
! 886: memset(&sc->sc_txtapu, 0, sizeof(sc->sc_txtapu));
! 887: sc->sc_txtap.at_ihdr.it_len = sizeof(sc->sc_txtapu);
! 888: sc->sc_txtap.at_ihdr.it_present = ATW_TX_RADIOTAP_PRESENT;
! 889:
! 890: return;
! 891:
! 892: /*
! 893: * Free any resources we've allocated during the failed attach
! 894: * attempt. Do this in reverse order and fall through.
! 895: */
! 896: fail_5:
! 897: for (i = 0; i < ATW_NRXDESC; i++) {
! 898: if (sc->sc_rxsoft[i].rxs_dmamap == NULL)
! 899: continue;
! 900: bus_dmamap_destroy(sc->sc_dmat, sc->sc_rxsoft[i].rxs_dmamap);
! 901: }
! 902: fail_4:
! 903: for (i = 0; i < ATW_TXQUEUELEN; i++) {
! 904: if (sc->sc_txsoft[i].txs_dmamap == NULL)
! 905: continue;
! 906: bus_dmamap_destroy(sc->sc_dmat, sc->sc_txsoft[i].txs_dmamap);
! 907: }
! 908: bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap);
! 909: fail_3:
! 910: bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap);
! 911: fail_2:
! 912: bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_control_data,
! 913: sizeof(struct atw_control_data));
! 914: fail_1:
! 915: bus_dmamem_free(sc->sc_dmat, &sc->sc_cdseg, sc->sc_cdnseg);
! 916: fail_0:
! 917: return;
! 918: }
! 919:
! 920: struct ieee80211_node *
! 921: atw_node_alloc(struct ieee80211com *ic)
! 922: {
! 923: struct atw_softc *sc = (struct atw_softc *)ic->ic_if.if_softc;
! 924: struct ieee80211_node *ni = (*sc->sc_node_alloc)(ic);
! 925:
! 926: DPRINTF(sc, ("%s: alloc node %p\n", sc->sc_dev.dv_xname, ni));
! 927: return ni;
! 928: }
! 929:
! 930: void
! 931: atw_node_free(struct ieee80211com *ic, struct ieee80211_node *ni)
! 932: {
! 933: struct atw_softc *sc = (struct atw_softc *)ic->ic_if.if_softc;
! 934:
! 935: DPRINTF(sc, ("%s: freeing node %p %s\n", sc->sc_dev.dv_xname, ni,
! 936: ether_sprintf(ni->ni_bssid)));
! 937: (*sc->sc_node_free)(ic, ni);
! 938: }
! 939:
! 940:
! 941: static void
! 942: atw_test1_reset(struct atw_softc *sc)
! 943: {
! 944: switch (sc->sc_rev) {
! 945: case ATW_REVISION_BA:
! 946: if (1 /* XXX condition on transceiver type */) {
! 947: ATW_SET(sc, ATW_TEST1, ATW_TEST1_TESTMODE_MONITOR);
! 948: }
! 949: break;
! 950: case ATW_REVISION_CA:
! 951: ATW_CLR(sc, ATW_TEST1, ATW_TEST1_TESTMODE_MASK);
! 952: break;
! 953: default:
! 954: break;
! 955: }
! 956: }
! 957:
! 958: /*
! 959: * atw_reset:
! 960: *
! 961: * Perform a soft reset on the ADM8211.
! 962: */
! 963: void
! 964: atw_reset(struct atw_softc *sc)
! 965: {
! 966: int i;
! 967: uint32_t lpc;
! 968:
! 969: ATW_WRITE(sc, ATW_NAR, 0x0);
! 970: DELAY(20 * 1000);
! 971:
! 972: /* Reference driver has a cryptic remark indicating that this might
! 973: * power-on the chip. I know that it turns off power-saving....
! 974: */
! 975: ATW_WRITE(sc, ATW_FRCTL, 0x0);
! 976:
! 977: ATW_WRITE(sc, ATW_PAR, ATW_PAR_SWR);
! 978:
! 979: for (i = 0; i < 50; i++) {
! 980: if (ATW_READ(sc, ATW_PAR) == 0)
! 981: break;
! 982: DELAY(1000);
! 983: }
! 984:
! 985: /* ... and then pause 100ms longer for good measure. */
! 986: DELAY(100 * 1000);
! 987:
! 988: DPRINTF2(sc, ("%s: atw_reset %d iterations\n", sc->sc_dev.dv_xname, i));
! 989:
! 990: if (ATW_ISSET(sc, ATW_PAR, ATW_PAR_SWR))
! 991: printf("%s: reset failed to complete\n", sc->sc_dev.dv_xname);
! 992:
! 993: atw_test1_reset(sc);
! 994: /*
! 995: * Initialize the PCI Access Register.
! 996: */
! 997: sc->sc_busmode = ATW_PAR_PBL_8DW;
! 998:
! 999: ATW_WRITE(sc, ATW_PAR, sc->sc_busmode);
! 1000: DPRINTF(sc, ("%s: ATW_PAR %08x busmode %08x\n", sc->sc_dev.dv_xname,
! 1001: ATW_READ(sc, ATW_PAR), sc->sc_busmode));
! 1002:
! 1003: /* Turn off maximum power saving, etc.
! 1004: *
! 1005: * XXX Following example of reference driver, should I set
! 1006: * an AID of 1? It didn't seem to help....
! 1007: */
! 1008: ATW_WRITE(sc, ATW_FRCTL, 0x0);
! 1009:
! 1010: DELAY(100 * 1000);
! 1011:
! 1012: /* Recall EEPROM. */
! 1013: ATW_SET(sc, ATW_TEST0, ATW_TEST0_EPRLD);
! 1014:
! 1015: DELAY(10 * 1000);
! 1016:
! 1017: lpc = ATW_READ(sc, ATW_LPC);
! 1018:
! 1019: DPRINTF(sc, ("%s: ATW_LPC %#08x\n", __func__, lpc));
! 1020:
! 1021: /* A reset seems to affect the SRAM contents, so put them into
! 1022: * a known state.
! 1023: */
! 1024: atw_clear_sram(sc);
! 1025:
! 1026: memset(sc->sc_bssid, 0xff, sizeof(sc->sc_bssid));
! 1027: }
! 1028:
! 1029: void
! 1030: atw_clear_sram(struct atw_softc *sc)
! 1031: {
! 1032: memset(sc->sc_sram, 0, sizeof(sc->sc_sram));
! 1033: /* XXX not for revision 0x20. */
! 1034: atw_write_sram(sc, 0, sc->sc_sram, sc->sc_sramlen);
! 1035: }
! 1036:
! 1037: /* TBD atw_init
! 1038: *
! 1039: * set MAC based on ic->ic_bss->myaddr
! 1040: * write WEP keys
! 1041: * set TX rate
! 1042: */
! 1043:
! 1044: /* Tell the ADM8211 to raise ATW_INTR_LINKOFF if 7 beacon intervals pass
! 1045: * without receiving a beacon with the preferred BSSID & SSID.
! 1046: * atw_write_bssid & atw_write_ssid set the BSSID & SSID.
! 1047: */
! 1048: void
! 1049: atw_wcsr_init(struct atw_softc *sc)
! 1050: {
! 1051: uint32_t wcsr;
! 1052:
! 1053: wcsr = ATW_READ(sc, ATW_WCSR);
! 1054: wcsr &= ~(ATW_WCSR_BLN_MASK|ATW_WCSR_LSOE|ATW_WCSR_MPRE|ATW_WCSR_LSOE);
! 1055: wcsr |= LSHIFT(7, ATW_WCSR_BLN_MASK);
! 1056: ATW_WRITE(sc, ATW_WCSR, wcsr); /* XXX resets wake-up status bits */
! 1057:
! 1058: DPRINTF(sc, ("%s: %s reg[WCSR] = %08x\n",
! 1059: sc->sc_dev.dv_xname, __func__, ATW_READ(sc, ATW_WCSR)));
! 1060: }
! 1061:
! 1062: /* Turn off power management. Set Rx store-and-forward mode. */
! 1063: void
! 1064: atw_cmdr_init(struct atw_softc *sc)
! 1065: {
! 1066: uint32_t cmdr;
! 1067: cmdr = ATW_READ(sc, ATW_CMDR);
! 1068: cmdr &= ~ATW_CMDR_APM;
! 1069: cmdr |= ATW_CMDR_RTE;
! 1070: cmdr &= ~ATW_CMDR_DRT_MASK;
! 1071: cmdr |= ATW_CMDR_DRT_SF;
! 1072:
! 1073: ATW_WRITE(sc, ATW_CMDR, cmdr);
! 1074: }
! 1075:
! 1076: void
! 1077: atw_tofs2_init(struct atw_softc *sc)
! 1078: {
! 1079: uint32_t tofs2;
! 1080: /* XXX this magic can probably be figured out from the RFMD docs */
! 1081: #ifndef ATW_REFSLAVE
! 1082: tofs2 = LSHIFT(4, ATW_TOFS2_PWR1UP_MASK) | /* 8 ms = 4 * 2 ms */
! 1083: LSHIFT(13, ATW_TOFS2_PWR0PAPE_MASK) | /* 13 us */
! 1084: LSHIFT(8, ATW_TOFS2_PWR1PAPE_MASK) | /* 8 us */
! 1085: LSHIFT(5, ATW_TOFS2_PWR0TRSW_MASK) | /* 5 us */
! 1086: LSHIFT(12, ATW_TOFS2_PWR1TRSW_MASK) | /* 12 us */
! 1087: LSHIFT(13, ATW_TOFS2_PWR0PE2_MASK) | /* 13 us */
! 1088: LSHIFT(4, ATW_TOFS2_PWR1PE2_MASK) | /* 4 us */
! 1089: LSHIFT(5, ATW_TOFS2_PWR0TXPE_MASK); /* 5 us */
! 1090: #else
! 1091: /* XXX new magic from reference driver source */
! 1092: tofs2 = LSHIFT(8, ATW_TOFS2_PWR1UP_MASK) | /* 8 ms = 4 * 2 ms */
! 1093: LSHIFT(8, ATW_TOFS2_PWR0PAPE_MASK) | /* 13 us */
! 1094: LSHIFT(1, ATW_TOFS2_PWR1PAPE_MASK) | /* 8 us */
! 1095: LSHIFT(5, ATW_TOFS2_PWR0TRSW_MASK) | /* 5 us */
! 1096: LSHIFT(12, ATW_TOFS2_PWR1TRSW_MASK) | /* 12 us */
! 1097: LSHIFT(13, ATW_TOFS2_PWR0PE2_MASK) | /* 13 us */
! 1098: LSHIFT(1, ATW_TOFS2_PWR1PE2_MASK) | /* 4 us */
! 1099: LSHIFT(8, ATW_TOFS2_PWR0TXPE_MASK); /* 5 us */
! 1100: #endif
! 1101: ATW_WRITE(sc, ATW_TOFS2, tofs2);
! 1102: }
! 1103:
! 1104: void
! 1105: atw_nar_init(struct atw_softc *sc)
! 1106: {
! 1107: ATW_WRITE(sc, ATW_NAR, ATW_NAR_SF|ATW_NAR_PB);
! 1108: }
! 1109:
! 1110: void
! 1111: atw_txlmt_init(struct atw_softc *sc)
! 1112: {
! 1113: ATW_WRITE(sc, ATW_TXLMT, LSHIFT(512, ATW_TXLMT_MTMLT_MASK) |
! 1114: LSHIFT(1, ATW_TXLMT_SRTYLIM_MASK));
! 1115: }
! 1116:
! 1117: void
! 1118: atw_test1_init(struct atw_softc *sc)
! 1119: {
! 1120: uint32_t test1;
! 1121:
! 1122: test1 = ATW_READ(sc, ATW_TEST1);
! 1123: test1 &= ~(ATW_TEST1_DBGREAD_MASK|ATW_TEST1_CONTROL);
! 1124: /* XXX magic 0x1 */
! 1125: test1 |= LSHIFT(0x1, ATW_TEST1_DBGREAD_MASK) | ATW_TEST1_CONTROL;
! 1126: ATW_WRITE(sc, ATW_TEST1, test1);
! 1127: }
! 1128:
! 1129: void
! 1130: atw_rf_reset(struct atw_softc *sc)
! 1131: {
! 1132: /* XXX this resets an Intersil RF front-end? */
! 1133: /* TBD condition on Intersil RFType? */
! 1134: ATW_WRITE(sc, ATW_SYNRF, ATW_SYNRF_INTERSIL_EN);
! 1135: DELAY(10 * 1000);
! 1136: ATW_WRITE(sc, ATW_SYNRF, 0);
! 1137: DELAY(5 * 1000);
! 1138: }
! 1139:
! 1140: /* Set 16 TU max duration for the contention-free period (CFP). */
! 1141: void
! 1142: atw_cfp_init(struct atw_softc *sc)
! 1143: {
! 1144: uint32_t cfpp;
! 1145:
! 1146: cfpp = ATW_READ(sc, ATW_CFPP);
! 1147: cfpp &= ~ATW_CFPP_CFPMD;
! 1148: cfpp |= LSHIFT(16, ATW_CFPP_CFPMD);
! 1149: ATW_WRITE(sc, ATW_CFPP, cfpp);
! 1150: }
! 1151:
! 1152: void
! 1153: atw_tofs0_init(struct atw_softc *sc)
! 1154: {
! 1155: /* XXX I guess that the Cardbus clock is 22MHz?
! 1156: * I am assuming that the role of ATW_TOFS0_USCNT is
! 1157: * to divide the bus clock to get a 1MHz clock---the datasheet is not
! 1158: * very clear on this point. It says in the datasheet that it is
! 1159: * possible for the ADM8211 to accomodate bus speeds between 22MHz
! 1160: * and 33MHz; maybe this is the way? I see a binary-only driver write
! 1161: * these values. These values are also the power-on default.
! 1162: */
! 1163: ATW_WRITE(sc, ATW_TOFS0,
! 1164: LSHIFT(22, ATW_TOFS0_USCNT_MASK) |
! 1165: ATW_TOFS0_TUCNT_MASK /* set all bits in TUCNT */);
! 1166: }
! 1167:
! 1168: /* Initialize interframe spacing: 802.11b slot time, SIFS, DIFS, EIFS. */
! 1169: void
! 1170: atw_ifs_init(struct atw_softc *sc)
! 1171: {
! 1172: uint32_t ifst;
! 1173: /* XXX EIFS=0x64, SIFS=110 are used by the reference driver.
! 1174: * Go figure.
! 1175: */
! 1176: ifst = LSHIFT(IEEE80211_DUR_DS_SLOT, ATW_IFST_SLOT_MASK) |
! 1177: LSHIFT(22 * 5 /* IEEE80211_DUR_DS_SIFS */ /* # of 22MHz cycles */,
! 1178: ATW_IFST_SIFS_MASK) |
! 1179: LSHIFT(IEEE80211_DUR_DS_DIFS, ATW_IFST_DIFS_MASK) |
! 1180: LSHIFT(0x64 /* IEEE80211_DUR_DS_EIFS */, ATW_IFST_EIFS_MASK);
! 1181:
! 1182: ATW_WRITE(sc, ATW_IFST, ifst);
! 1183: }
! 1184:
! 1185: void
! 1186: atw_response_times_init(struct atw_softc *sc)
! 1187: {
! 1188: /* XXX More magic. Relates to ACK timing? The datasheet seems to
! 1189: * indicate that the MAC expects at least SIFS + MIRT microseconds
! 1190: * to pass after it transmits a frame that requires a response;
! 1191: * it waits at most SIFS + MART microseconds for the response.
! 1192: * Surely this is not the ACK timeout?
! 1193: */
! 1194: ATW_WRITE(sc, ATW_RSPT, LSHIFT(0xffff, ATW_RSPT_MART_MASK) |
! 1195: LSHIFT(0xff, ATW_RSPT_MIRT_MASK));
! 1196: }
! 1197:
! 1198: /* Set up the MMI read/write addresses for the baseband. The Tx/Rx
! 1199: * engines read and write baseband registers after Rx and before
! 1200: * Tx, respectively.
! 1201: */
! 1202: void
! 1203: atw_bbp_io_init(struct atw_softc *sc)
! 1204: {
! 1205: uint32_t mmiraddr2;
! 1206:
! 1207: /* XXX The reference driver does this, but is it *really*
! 1208: * necessary?
! 1209: */
! 1210: switch (sc->sc_rev) {
! 1211: case ATW_REVISION_AB:
! 1212: case ATW_REVISION_AF:
! 1213: mmiraddr2 = 0x0;
! 1214: break;
! 1215: default:
! 1216: mmiraddr2 = ATW_READ(sc, ATW_MMIRADDR2);
! 1217: mmiraddr2 &=
! 1218: ~(ATW_MMIRADDR2_PROREXT|ATW_MMIRADDR2_PRORLEN_MASK);
! 1219: break;
! 1220: }
! 1221:
! 1222: switch (sc->sc_bbptype) {
! 1223: case ATW_BBPTYPE_INTERSIL:
! 1224: ATW_WRITE(sc, ATW_MMIWADDR, ATW_MMIWADDR_INTERSIL);
! 1225: ATW_WRITE(sc, ATW_MMIRADDR1, ATW_MMIRADDR1_INTERSIL);
! 1226: mmiraddr2 |= ATW_MMIRADDR2_INTERSIL;
! 1227: break;
! 1228: case ATW_BBPTYPE_MARVEL:
! 1229: /* TBD find out the Marvel settings. */
! 1230: break;
! 1231: case ATW_BBPTYPE_RFMD:
! 1232: default:
! 1233: ATW_WRITE(sc, ATW_MMIWADDR, ATW_MMIWADDR_RFMD);
! 1234: ATW_WRITE(sc, ATW_MMIRADDR1, ATW_MMIRADDR1_RFMD);
! 1235: mmiraddr2 |= ATW_MMIRADDR2_RFMD;
! 1236: break;
! 1237: }
! 1238: ATW_WRITE(sc, ATW_MMIRADDR2, mmiraddr2);
! 1239:
! 1240: atw_si4126_init(sc);
! 1241:
! 1242: ATW_WRITE(sc, ATW_MACTEST, ATW_MACTEST_MMI_USETXCLK);
! 1243: }
! 1244:
! 1245: void
! 1246: atw_si4126_init(struct atw_softc *sc)
! 1247: {
! 1248: switch (sc->sc_rftype) {
! 1249: case ATW_RFTYPE_RFMD:
! 1250: if (sc->sc_rev >= ATW_REVISION_BA) {
! 1251: atw_si4126_write(sc, 0x1f, 0x00000);
! 1252: atw_si4126_write(sc, 0x0c, 0x3001f);
! 1253: atw_si4126_write(sc, SI4126_GAIN, 0x29c03);
! 1254: atw_si4126_write(sc, SI4126_RF1N, 0x1ff6f);
! 1255: atw_si4126_write(sc, SI4126_RF2N, 0x29403);
! 1256: atw_si4126_write(sc, SI4126_RF2R, 0x1456f);
! 1257: atw_si4126_write(sc, 0x09, 0x10050);
! 1258: atw_si4126_write(sc, SI4126_IFR, 0x3fff8);
! 1259: }
! 1260: break;
! 1261: default:
! 1262: break;
! 1263: }
! 1264: }
! 1265:
! 1266: /*
! 1267: * atw_init: [ ifnet interface function ]
! 1268: *
! 1269: * Initialize the interface. Must be called at splnet().
! 1270: */
! 1271: int
! 1272: atw_init(struct ifnet *ifp)
! 1273: {
! 1274: struct atw_softc *sc = ifp->if_softc;
! 1275: struct ieee80211com *ic = &sc->sc_ic;
! 1276: struct atw_txsoft *txs;
! 1277: struct atw_rxsoft *rxs;
! 1278: int i, error = 0;
! 1279:
! 1280: if ((error = atw_enable(sc)) != 0)
! 1281: goto out;
! 1282:
! 1283: /*
! 1284: * Cancel any pending I/O. This also resets.
! 1285: */
! 1286: atw_stop(ifp, 0);
! 1287:
! 1288: ic->ic_bss->ni_chan = ic->ic_ibss_chan;
! 1289: DPRINTF(sc, ("%s: channel %d freq %d flags 0x%04x\n",
! 1290: __func__, ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan),
! 1291: ic->ic_bss->ni_chan->ic_freq, ic->ic_bss->ni_chan->ic_flags));
! 1292:
! 1293: atw_wcsr_init(sc);
! 1294:
! 1295: atw_cmdr_init(sc);
! 1296:
! 1297: /* Set data rate for PLCP Signal field, 1Mbps = 10 x 100Kb/s.
! 1298: *
! 1299: * XXX Set transmit power for ATIM, RTS, Beacon.
! 1300: */
! 1301: ATW_WRITE(sc, ATW_PLCPHD, LSHIFT(10, ATW_PLCPHD_SIGNAL_MASK) |
! 1302: LSHIFT(0xb0, ATW_PLCPHD_SERVICE_MASK));
! 1303:
! 1304: atw_tofs2_init(sc);
! 1305:
! 1306: atw_nar_init(sc);
! 1307:
! 1308: atw_txlmt_init(sc);
! 1309:
! 1310: atw_test1_init(sc);
! 1311:
! 1312: atw_rf_reset(sc);
! 1313:
! 1314: atw_cfp_init(sc);
! 1315:
! 1316: atw_tofs0_init(sc);
! 1317:
! 1318: atw_ifs_init(sc);
! 1319:
! 1320: /* XXX Fall asleep after one second of inactivity.
! 1321: * XXX A frame may only dribble in for 65536us.
! 1322: */
! 1323: ATW_WRITE(sc, ATW_RMD,
! 1324: LSHIFT(1, ATW_RMD_PCNT) | LSHIFT(0xffff, ATW_RMD_RMRD_MASK));
! 1325:
! 1326: atw_response_times_init(sc);
! 1327:
! 1328: atw_bbp_io_init(sc);
! 1329:
! 1330: ATW_WRITE(sc, ATW_STSR, 0xffffffff);
! 1331:
! 1332: if ((error = atw_rf3000_init(sc)) != 0)
! 1333: goto out;
! 1334:
! 1335: ATW_WRITE(sc, ATW_PAR, sc->sc_busmode);
! 1336: DPRINTF(sc, ("%s: ATW_PAR %08x busmode %08x\n", sc->sc_dev.dv_xname,
! 1337: ATW_READ(sc, ATW_PAR), sc->sc_busmode));
! 1338:
! 1339: /*
! 1340: * Initialize the transmit descriptor ring.
! 1341: */
! 1342: memset(sc->sc_txdescs, 0, sizeof(sc->sc_txdescs));
! 1343: for (i = 0; i < ATW_NTXDESC; i++) {
! 1344: sc->sc_txdescs[i].at_ctl = 0;
! 1345: /* no transmit chaining */
! 1346: sc->sc_txdescs[i].at_flags = 0 /* ATW_TXFLAG_TCH */;
! 1347: sc->sc_txdescs[i].at_buf2 =
! 1348: htole32(ATW_CDTXADDR(sc, ATW_NEXTTX(i)));
! 1349: }
! 1350: /* use ring mode */
! 1351: sc->sc_txdescs[ATW_NTXDESC - 1].at_flags |= htole32(ATW_TXFLAG_TER);
! 1352: ATW_CDTXSYNC(sc, 0, ATW_NTXDESC,
! 1353: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
! 1354: sc->sc_txfree = ATW_NTXDESC;
! 1355: sc->sc_txnext = 0;
! 1356:
! 1357: /*
! 1358: * Initialize the transmit job descriptors.
! 1359: */
! 1360: SIMPLEQ_INIT(&sc->sc_txfreeq);
! 1361: SIMPLEQ_INIT(&sc->sc_txdirtyq);
! 1362: for (i = 0; i < ATW_TXQUEUELEN; i++) {
! 1363: txs = &sc->sc_txsoft[i];
! 1364: txs->txs_mbuf = NULL;
! 1365: SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
! 1366: }
! 1367:
! 1368: /*
! 1369: * Initialize the receive descriptor and receive job
! 1370: * descriptor rings.
! 1371: */
! 1372: for (i = 0; i < ATW_NRXDESC; i++) {
! 1373: rxs = &sc->sc_rxsoft[i];
! 1374: if (rxs->rxs_mbuf == NULL) {
! 1375: if ((error = atw_add_rxbuf(sc, i)) != 0) {
! 1376: printf("%s: unable to allocate or map rx "
! 1377: "buffer %d, error = %d\n",
! 1378: sc->sc_dev.dv_xname, i, error);
! 1379: /*
! 1380: * XXX Should attempt to run with fewer receive
! 1381: * XXX buffers instead of just failing.
! 1382: */
! 1383: atw_rxdrain(sc);
! 1384: goto out;
! 1385: }
! 1386: } else
! 1387: ATW_INIT_RXDESC(sc, i);
! 1388: }
! 1389: sc->sc_rxptr = 0;
! 1390:
! 1391: /*
! 1392: * Initialize the interrupt mask and enable interrupts.
! 1393: */
! 1394: /* normal interrupts */
! 1395: sc->sc_inten = ATW_INTR_TCI | ATW_INTR_TDU | ATW_INTR_RCI |
! 1396: ATW_INTR_NISS | ATW_INTR_LINKON | ATW_INTR_BCNTC;
! 1397:
! 1398: /* abnormal interrupts */
! 1399: sc->sc_inten |= ATW_INTR_TPS | ATW_INTR_TLT | ATW_INTR_TRT |
! 1400: ATW_INTR_TUF | ATW_INTR_RDU | ATW_INTR_RPS | ATW_INTR_AISS |
! 1401: ATW_INTR_FBE | ATW_INTR_LINKOFF | ATW_INTR_TSFTF | ATW_INTR_TSCZ;
! 1402:
! 1403: sc->sc_linkint_mask = ATW_INTR_LINKON | ATW_INTR_LINKOFF |
! 1404: ATW_INTR_BCNTC | ATW_INTR_TSFTF | ATW_INTR_TSCZ;
! 1405: sc->sc_rxint_mask = ATW_INTR_RCI | ATW_INTR_RDU;
! 1406: sc->sc_txint_mask = ATW_INTR_TCI | ATW_INTR_TUF | ATW_INTR_TLT |
! 1407: ATW_INTR_TRT;
! 1408:
! 1409: sc->sc_linkint_mask &= sc->sc_inten;
! 1410: sc->sc_rxint_mask &= sc->sc_inten;
! 1411: sc->sc_txint_mask &= sc->sc_inten;
! 1412:
! 1413: ATW_WRITE(sc, ATW_IER, sc->sc_inten);
! 1414: ATW_WRITE(sc, ATW_STSR, 0xffffffff);
! 1415:
! 1416: DPRINTF(sc, ("%s: ATW_IER %08x, inten %08x\n",
! 1417: sc->sc_dev.dv_xname, ATW_READ(sc, ATW_IER), sc->sc_inten));
! 1418:
! 1419: /*
! 1420: * Give the transmit and receive rings to the ADM8211.
! 1421: */
! 1422: ATW_WRITE(sc, ATW_RDB, ATW_CDRXADDR(sc, sc->sc_rxptr));
! 1423: ATW_WRITE(sc, ATW_TDBD, ATW_CDTXADDR(sc, sc->sc_txnext));
! 1424:
! 1425: sc->sc_txthresh = 0;
! 1426: sc->sc_opmode = ATW_NAR_SR | ATW_NAR_ST |
! 1427: sc->sc_txth[sc->sc_txthresh].txth_opmode;
! 1428:
! 1429: /* common 802.11 configuration */
! 1430: ic->ic_flags &= ~IEEE80211_F_IBSSON;
! 1431: switch (ic->ic_opmode) {
! 1432: case IEEE80211_M_STA:
! 1433: break;
! 1434: case IEEE80211_M_AHDEMO: /* XXX */
! 1435: case IEEE80211_M_IBSS:
! 1436: ic->ic_flags |= IEEE80211_F_IBSSON;
! 1437: /*FALLTHROUGH*/
! 1438: case IEEE80211_M_HOSTAP: /* XXX */
! 1439: break;
! 1440: case IEEE80211_M_MONITOR: /* XXX */
! 1441: break;
! 1442: }
! 1443:
! 1444: switch (ic->ic_opmode) {
! 1445: case IEEE80211_M_AHDEMO:
! 1446: case IEEE80211_M_HOSTAP:
! 1447: ic->ic_bss->ni_intval = ic->ic_lintval;
! 1448: ic->ic_bss->ni_rssi = 0;
! 1449: ic->ic_bss->ni_rstamp = 0;
! 1450: break;
! 1451: default: /* XXX */
! 1452: break;
! 1453: }
! 1454:
! 1455: sc->sc_wepctl = 0;
! 1456:
! 1457: atw_write_ssid(sc);
! 1458: atw_write_sup_rates(sc);
! 1459: if (ic->ic_caps & IEEE80211_C_WEP)
! 1460: atw_write_wep(sc);
! 1461:
! 1462: ic->ic_state = IEEE80211_S_INIT;
! 1463:
! 1464: /*
! 1465: * Set the receive filter. This will start the transmit and
! 1466: * receive processes.
! 1467: */
! 1468: atw_filter_setup(sc);
! 1469:
! 1470: /*
! 1471: * Start the receive process.
! 1472: */
! 1473: ATW_WRITE(sc, ATW_RDR, 0x1);
! 1474:
! 1475: /*
! 1476: * Note that the interface is now running.
! 1477: */
! 1478: ifp->if_flags |= IFF_RUNNING;
! 1479: ifp->if_flags &= ~IFF_OACTIVE;
! 1480:
! 1481: /* send no beacons, yet. */
! 1482: atw_start_beacon(sc, 0);
! 1483:
! 1484: if (ic->ic_opmode == IEEE80211_M_MONITOR)
! 1485: error = ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
! 1486: else
! 1487: error = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
! 1488: out:
! 1489: if (error) {
! 1490: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
! 1491: ifp->if_timer = 0;
! 1492: printf("%s: interface not running\n", sc->sc_dev.dv_xname);
! 1493: }
! 1494: #ifdef ATW_DEBUG
! 1495: atw_print_regs(sc, "end of init");
! 1496: #endif /* ATW_DEBUG */
! 1497:
! 1498: return (error);
! 1499: }
! 1500:
! 1501: /* enable == 1: host control of RF3000/Si4126 through ATW_SYNCTL.
! 1502: * 0: MAC control of RF3000/Si4126.
! 1503: *
! 1504: * Applies power, or selects RF front-end? Sets reset condition.
! 1505: *
! 1506: * TBD support non-RFMD BBP, non-SiLabs synth.
! 1507: */
! 1508: void
! 1509: atw_bbp_io_enable(struct atw_softc *sc, int enable)
! 1510: {
! 1511: if (enable) {
! 1512: ATW_WRITE(sc, ATW_SYNRF,
! 1513: ATW_SYNRF_SELRF|ATW_SYNRF_PE1|ATW_SYNRF_PHYRST);
! 1514: DELAY(atw_bbp_io_enable_delay);
! 1515: } else {
! 1516: ATW_WRITE(sc, ATW_SYNRF, 0);
! 1517: DELAY(atw_bbp_io_disable_delay); /* shorter for some reason */
! 1518: }
! 1519: }
! 1520:
! 1521: int
! 1522: atw_tune(struct atw_softc *sc)
! 1523: {
! 1524: int rc;
! 1525: u_int chan;
! 1526: struct ieee80211com *ic = &sc->sc_ic;
! 1527:
! 1528: chan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
! 1529: if (chan == 0 || chan == IEEE80211_CHAN_ANY)
! 1530: return 0;
! 1531:
! 1532: if (chan == sc->sc_cur_chan)
! 1533: return 0;
! 1534:
! 1535: DPRINTF(sc, ("%s: chan %d -> %d\n", sc->sc_dev.dv_xname,
! 1536: sc->sc_cur_chan, chan));
! 1537:
! 1538: atw_idle(sc, ATW_NAR_SR|ATW_NAR_ST);
! 1539:
! 1540: atw_si4126_tune(sc, chan);
! 1541: if ((rc = atw_rf3000_tune(sc, chan)) != 0)
! 1542: printf("%s: failed to tune channel %d\n", sc->sc_dev.dv_xname,
! 1543: chan);
! 1544:
! 1545: ATW_WRITE(sc, ATW_NAR, sc->sc_opmode);
! 1546: DELAY(20 * 1000);
! 1547: ATW_WRITE(sc, ATW_RDR, 0x1);
! 1548:
! 1549: if (rc == 0)
! 1550: sc->sc_cur_chan = chan;
! 1551:
! 1552: return rc;
! 1553: }
! 1554:
! 1555: #ifdef ATW_SYNDEBUG
! 1556: void
! 1557: atw_si4126_print(struct atw_softc *sc)
! 1558: {
! 1559: struct ifnet *ifp = &sc->sc_ic.ic_if;
! 1560: u_int addr, val;
! 1561:
! 1562: if (atw_debug < 3 || (ifp->if_flags & IFF_DEBUG) == 0)
! 1563: return;
! 1564:
! 1565: for (addr = 0; addr <= 8; addr++) {
! 1566: printf("%s: synth[%d] = ", sc->sc_dev.dv_xname, addr);
! 1567: if (atw_si4126_read(sc, addr, &val) == 0) {
! 1568: printf("<unknown> (quitting print-out)\n");
! 1569: break;
! 1570: }
! 1571: printf("%05x\n", val);
! 1572: }
! 1573: }
! 1574: #endif /* ATW_SYNDEBUG */
! 1575:
! 1576: /* Tune to channel chan by adjusting the Si4126 RF/IF synthesizer.
! 1577: *
! 1578: * The RF/IF synthesizer produces two reference frequencies for
! 1579: * the RF2948B transceiver. The first frequency the RF2948B requires
! 1580: * is two times the so-called "intermediate frequency" (IF). Since
! 1581: * a SAW filter on the radio fixes the IF at 374MHz, I program the
! 1582: * Si4126 to generate IF LO = 374MHz x 2 = 748MHz. The second
! 1583: * frequency required by the transceiver is the radio frequency
! 1584: * (RF). This is a superheterodyne transceiver; for f(chan) the
! 1585: * center frequency of the channel we are tuning, RF = f(chan) -
! 1586: * IF.
! 1587: *
! 1588: * XXX I am told by SiLabs that the Si4126 will accept a broader range
! 1589: * of XIN than the 2-25MHz mentioned by the datasheet, even *without*
! 1590: * XINDIV2 = 1. I've tried this (it is necessary to double R) and it
! 1591: * works, but I have still programmed for XINDIV2 = 1 to be safe.
! 1592: */
! 1593: void
! 1594: atw_si4126_tune(struct atw_softc *sc, u_int chan)
! 1595: {
! 1596: u_int mhz;
! 1597: u_int R;
! 1598: u_int32_t gpio;
! 1599: u_int16_t gain;
! 1600:
! 1601: #ifdef ATW_SYNDEBUG
! 1602: atw_si4126_print(sc);
! 1603: #endif /* ATW_SYNDEBUG */
! 1604:
! 1605: if (sc->sc_rev >= ATW_REVISION_BA) {
! 1606: atw_si4126_write(sc, SI4126_MAIN, 0x04007);
! 1607: atw_si4126_write(sc, SI4126_POWER, 0x00033);
! 1608: atw_si4126_write(sc, SI4126_IFN,
! 1609: atw_rfmd2958_ifn[chan - 1]);
! 1610: atw_si4126_write(sc, SI4126_RF1R,
! 1611: atw_rfmd2958_rf1r[chan - 1]);
! 1612: #ifdef NOTYET
! 1613: /* set TX POWER? */
! 1614: atw_si4126_write(sc, 0x0a,
! 1615: (sc->sc_srom[ATW_SR_CSR20] & mask) |
! 1616: power << 9);
! 1617: #endif
! 1618: /* set TX GAIN */
! 1619: atw_si4126_write(sc, 0x09, 0x00050 |
! 1620: sc->sc_srom[ATW_SR_TXPOWER(chan - 1)]);
! 1621: /* wait 100us from power-up for RF, IF to settle */
! 1622: DELAY(100);
! 1623:
! 1624: return;
! 1625: }
! 1626:
! 1627: if (chan == 14)
! 1628: mhz = 2484;
! 1629: else
! 1630: mhz = 2412 + 5 * (chan - 1);
! 1631:
! 1632: /* Tune IF to 748MHz to suit the IF LO input of the
! 1633: * RF2494B, which is 2 x IF. No need to set an IF divider
! 1634: * because an IF in 526MHz - 952MHz is allowed.
! 1635: *
! 1636: * XIN is 44.000MHz, so divide it by two to get allowable
! 1637: * range of 2-25MHz. SiLabs tells me that this is not
! 1638: * strictly necessary.
! 1639: */
! 1640:
! 1641: if (atw_xindiv2)
! 1642: R = 44;
! 1643: else
! 1644: R = 88;
! 1645:
! 1646: /* Power-up RF, IF synthesizers. */
! 1647: atw_si4126_write(sc, SI4126_POWER,
! 1648: SI4126_POWER_PDIB|SI4126_POWER_PDRB);
! 1649:
! 1650: /* set LPWR, too? */
! 1651: atw_si4126_write(sc, SI4126_MAIN,
! 1652: (atw_xindiv2) ? SI4126_MAIN_XINDIV2 : 0);
! 1653:
! 1654: /* Set the phase-locked loop gain. If RF2 N > 2047, then
! 1655: * set KP2 to 1.
! 1656: *
! 1657: * REFDIF This is different from the reference driver, which
! 1658: * always sets SI4126_GAIN to 0.
! 1659: */
! 1660: gain = LSHIFT(((mhz - 374) > 2047) ? 1 : 0, SI4126_GAIN_KP2_MASK);
! 1661:
! 1662: atw_si4126_write(sc, SI4126_GAIN, gain);
! 1663:
! 1664: /* XIN = 44MHz.
! 1665: *
! 1666: * If XINDIV2 = 1, IF = N/(2 * R) * XIN. I choose N = 1496,
! 1667: * R = 44 so that 1496/(2 * 44) * 44MHz = 748MHz.
! 1668: *
! 1669: * If XINDIV2 = 0, IF = N/R * XIN. I choose N = 1496, R = 88
! 1670: * so that 1496/88 * 44MHz = 748MHz.
! 1671: */
! 1672: atw_si4126_write(sc, SI4126_IFN, 1496);
! 1673:
! 1674: atw_si4126_write(sc, SI4126_IFR, R);
! 1675:
! 1676: #ifndef ATW_REFSLAVE
! 1677: /* Set RF1 arbitrarily. DO NOT configure RF1 after RF2, because
! 1678: * then RF1 becomes the active RF synthesizer, even on the Si4126,
! 1679: * which has no RF1!
! 1680: */
! 1681: atw_si4126_write(sc, SI4126_RF1R, R);
! 1682:
! 1683: atw_si4126_write(sc, SI4126_RF1N, mhz - 374);
! 1684: #endif
! 1685:
! 1686: /* N/R * XIN = RF. XIN = 44MHz. We desire RF = mhz - IF,
! 1687: * where IF = 374MHz. Let's divide XIN to 1MHz. So R = 44.
! 1688: * Now let's multiply it to mhz. So mhz - IF = N.
! 1689: */
! 1690: atw_si4126_write(sc, SI4126_RF2R, R);
! 1691:
! 1692: atw_si4126_write(sc, SI4126_RF2N, mhz - 374);
! 1693:
! 1694: /* wait 100us from power-up for RF, IF to settle */
! 1695: DELAY(100);
! 1696:
! 1697: gpio = ATW_READ(sc, ATW_GPIO);
! 1698: gpio &= ~(ATW_GPIO_EN_MASK|ATW_GPIO_O_MASK|ATW_GPIO_I_MASK);
! 1699: gpio |= LSHIFT(1, ATW_GPIO_EN_MASK);
! 1700:
! 1701: if ((sc->sc_if.if_flags & IFF_LINK1) != 0 && chan != 14) {
! 1702: /* Set a Prism RF front-end to a special mode for channel 14?
! 1703: *
! 1704: * Apparently the SMC2635W needs this, although I don't think
! 1705: * it has a Prism RF.
! 1706: */
! 1707: gpio |= LSHIFT(1, ATW_GPIO_O_MASK);
! 1708: }
! 1709: ATW_WRITE(sc, ATW_GPIO, gpio);
! 1710:
! 1711: #ifdef ATW_SYNDEBUG
! 1712: atw_si4126_print(sc);
! 1713: #endif /* ATW_SYNDEBUG */
! 1714: }
! 1715:
! 1716: /* Baseline initialization of RF3000 BBP: set CCA mode and enable antenna
! 1717: * diversity.
! 1718: *
! 1719: * !!!
! 1720: * !!! Call this w/ Tx/Rx suspended, atw_idle(, ATW_NAR_ST|ATW_NAR_SR).
! 1721: * !!!
! 1722: */
! 1723: int
! 1724: atw_rf3000_init(struct atw_softc *sc)
! 1725: {
! 1726: int rc = 0;
! 1727:
! 1728: atw_bbp_io_enable(sc, 1);
! 1729:
! 1730: /* CCA is acquisition sensitive */
! 1731: rc = atw_rf3000_write(sc, RF3000_CCACTL,
! 1732: LSHIFT(RF3000_CCACTL_MODE_BOTH, RF3000_CCACTL_MODE_MASK));
! 1733:
! 1734: if (rc != 0)
! 1735: goto out;
! 1736:
! 1737: /* enable diversity */
! 1738: rc = atw_rf3000_write(sc, RF3000_DIVCTL, RF3000_DIVCTL_ENABLE);
! 1739:
! 1740: if (rc != 0)
! 1741: goto out;
! 1742:
! 1743: /* sensible setting from a binary-only driver */
! 1744: rc = atw_rf3000_write(sc, RF3000_GAINCTL,
! 1745: LSHIFT(0x1d, RF3000_GAINCTL_TXVGC_MASK));
! 1746:
! 1747: if (rc != 0)
! 1748: goto out;
! 1749:
! 1750: /* magic from a binary-only driver */
! 1751: rc = atw_rf3000_write(sc, RF3000_LOGAINCAL,
! 1752: LSHIFT(0x38, RF3000_LOGAINCAL_CAL_MASK));
! 1753:
! 1754: if (rc != 0)
! 1755: goto out;
! 1756:
! 1757: rc = atw_rf3000_write(sc, RF3000_HIGAINCAL, RF3000_HIGAINCAL_DSSSPAD);
! 1758:
! 1759: if (rc != 0)
! 1760: goto out;
! 1761:
! 1762: /*
! 1763: * XXX Reference driver remarks that Abocom sets this to 50.
! 1764: * Meaning 0x50, I think.... 50 = 0x32, which would set a bit
! 1765: * in the "reserved" area of register RF3000_OPTIONS1.
! 1766: */
! 1767: rc = atw_rf3000_write(sc, RF3000_OPTIONS1, sc->sc_rf3000_options1);
! 1768:
! 1769: if (rc != 0)
! 1770: goto out;
! 1771:
! 1772: rc = atw_rf3000_write(sc, RF3000_OPTIONS2, sc->sc_rf3000_options2);
! 1773:
! 1774: if (rc != 0)
! 1775: goto out;
! 1776:
! 1777: out:
! 1778: atw_bbp_io_enable(sc, 0);
! 1779: return rc;
! 1780: }
! 1781:
! 1782: #ifdef ATW_BBPDEBUG
! 1783: void
! 1784: atw_rf3000_print(struct atw_softc *sc)
! 1785: {
! 1786: struct ifnet *ifp = &sc->sc_ic.ic_if;
! 1787: u_int addr, val;
! 1788:
! 1789: if (atw_debug < 3 || (ifp->if_flags & IFF_DEBUG) == 0)
! 1790: return;
! 1791:
! 1792: for (addr = 0x01; addr <= 0x15; addr++) {
! 1793: printf("%s: bbp[%d] = \n", sc->sc_dev.dv_xname, addr);
! 1794: if (atw_rf3000_read(sc, addr, &val) != 0) {
! 1795: printf("<unknown> (quitting print-out)\n");
! 1796: break;
! 1797: }
! 1798: printf("%08x\n", val);
! 1799: }
! 1800: }
! 1801: #endif /* ATW_BBPDEBUG */
! 1802:
! 1803: /* Set the power settings on the BBP for channel `chan'. */
! 1804: int
! 1805: atw_rf3000_tune(struct atw_softc *sc, u_int chan)
! 1806: {
! 1807: int rc = 0;
! 1808: u_int32_t reg;
! 1809: u_int16_t txpower, lpf_cutoff, lna_gs_thresh;
! 1810:
! 1811: txpower = sc->sc_srom[ATW_SR_TXPOWER(chan)];
! 1812: lpf_cutoff = sc->sc_srom[ATW_SR_LPF_CUTOFF(chan)];
! 1813: lna_gs_thresh = sc->sc_srom[ATW_SR_LNA_GS_THRESH(chan)];
! 1814:
! 1815: /* odd channels: LSB, even channels: MSB */
! 1816: if (chan % 2 == 1) {
! 1817: txpower &= 0xFF;
! 1818: lpf_cutoff &= 0xFF;
! 1819: lna_gs_thresh &= 0xFF;
! 1820: } else {
! 1821: txpower >>= 8;
! 1822: lpf_cutoff >>= 8;
! 1823: lna_gs_thresh >>= 8;
! 1824: }
! 1825:
! 1826: #ifdef ATW_BBPDEBUG
! 1827: atw_rf3000_print(sc);
! 1828: #endif /* ATW_BBPDEBUG */
! 1829:
! 1830: DPRINTF(sc, ("%s: chan %d txpower %02x, lpf_cutoff %02x, "
! 1831: "lna_gs_thresh %02x\n",
! 1832: sc->sc_dev.dv_xname, chan, txpower, lpf_cutoff, lna_gs_thresh));
! 1833:
! 1834: atw_bbp_io_enable(sc, 1);
! 1835:
! 1836: if ((rc = atw_rf3000_write(sc, RF3000_GAINCTL,
! 1837: LSHIFT(txpower, RF3000_GAINCTL_TXVGC_MASK))) != 0)
! 1838: goto out;
! 1839:
! 1840: if ((rc = atw_rf3000_write(sc, RF3000_LOGAINCAL, lpf_cutoff)) != 0)
! 1841: goto out;
! 1842:
! 1843: if ((rc = atw_rf3000_write(sc, RF3000_HIGAINCAL, lna_gs_thresh)) != 0)
! 1844: goto out;
! 1845:
! 1846: if ((rc = atw_rf3000_write(sc, RF3000_OPTIONS1, 0x0)) != 0)
! 1847: goto out;
! 1848:
! 1849: rc = atw_rf3000_write(sc, RF3000_OPTIONS2, RF3000_OPTIONS2_LNAGS_DELAY);
! 1850: if (rc != 0)
! 1851: goto out;
! 1852:
! 1853: #ifdef ATW_BBPDEBUG
! 1854: atw_rf3000_print(sc);
! 1855: #endif /* ATW_BBPDEBUG */
! 1856:
! 1857: out:
! 1858: atw_bbp_io_enable(sc, 0);
! 1859:
! 1860: /* set beacon, rts, atim transmit power */
! 1861: reg = ATW_READ(sc, ATW_PLCPHD);
! 1862: reg &= ~ATW_PLCPHD_SERVICE_MASK;
! 1863: reg |= LSHIFT(LSHIFT(txpower, RF3000_GAINCTL_TXVGC_MASK),
! 1864: ATW_PLCPHD_SERVICE_MASK);
! 1865: ATW_WRITE(sc, ATW_PLCPHD, reg);
! 1866: DELAY(2 * 1000);
! 1867:
! 1868: return rc;
! 1869: }
! 1870:
! 1871: /* Write a register on the RF3000 baseband processor using the
! 1872: * registers provided by the ADM8211 for this purpose.
! 1873: *
! 1874: * Return 0 on success.
! 1875: */
! 1876: int
! 1877: atw_rf3000_write(struct atw_softc *sc, u_int addr, u_int val)
! 1878: {
! 1879: u_int32_t reg;
! 1880: int i;
! 1881:
! 1882: reg = sc->sc_bbpctl_wr |
! 1883: LSHIFT(val & 0xff, ATW_BBPCTL_DATA_MASK) |
! 1884: LSHIFT(addr & 0x7f, ATW_BBPCTL_ADDR_MASK);
! 1885:
! 1886: for (i = 10; --i >= 0; ) {
! 1887: ATW_WRITE(sc, ATW_BBPCTL, reg);
! 1888: DELAY(2000);
! 1889: if (ATW_ISSET(sc, ATW_BBPCTL, ATW_BBPCTL_WR) == 0)
! 1890: break;
! 1891: }
! 1892:
! 1893: if (i < 0) {
! 1894: printf("%s: BBPCTL still busy\n", sc->sc_dev.dv_xname);
! 1895: return ETIMEDOUT;
! 1896: }
! 1897: return 0;
! 1898: }
! 1899:
! 1900: /* Read a register on the RF3000 baseband processor using the registers
! 1901: * the ADM8211 provides for this purpose.
! 1902: *
! 1903: * The 7-bit register address is addr. Record the 8-bit data in the register
! 1904: * in *val.
! 1905: *
! 1906: * Return 0 on success.
! 1907: *
! 1908: * XXX This does not seem to work. The ADM8211 must require more or
! 1909: * different magic to read the chip than to write it. Possibly some
! 1910: * of the magic I have derived from a binary-only driver concerns
! 1911: * the "chip address" (see the RF3000 manual).
! 1912: */
! 1913: #ifdef ATW_BBPDEBUG
! 1914: int
! 1915: atw_rf3000_read(struct atw_softc *sc, u_int addr, u_int *val)
! 1916: {
! 1917: u_int32_t reg;
! 1918: int i;
! 1919:
! 1920: for (i = 1000; --i >= 0; ) {
! 1921: if (ATW_ISSET(sc, ATW_BBPCTL, ATW_BBPCTL_RD|ATW_BBPCTL_WR) == 0)
! 1922: break;
! 1923: DELAY(100);
! 1924: }
! 1925:
! 1926: if (i < 0) {
! 1927: printf("%s: start atw_rf3000_read, BBPCTL busy\n",
! 1928: sc->sc_dev.dv_xname);
! 1929: return ETIMEDOUT;
! 1930: }
! 1931:
! 1932: reg = sc->sc_bbpctl_rd | LSHIFT(addr & 0x7f, ATW_BBPCTL_ADDR_MASK);
! 1933:
! 1934: ATW_WRITE(sc, ATW_BBPCTL, reg);
! 1935:
! 1936: for (i = 1000; --i >= 0; ) {
! 1937: DELAY(100);
! 1938: if (ATW_ISSET(sc, ATW_BBPCTL, ATW_BBPCTL_RD) == 0)
! 1939: break;
! 1940: }
! 1941:
! 1942: ATW_CLR(sc, ATW_BBPCTL, ATW_BBPCTL_RD);
! 1943:
! 1944: if (i < 0) {
! 1945: printf("%s: atw_rf3000_read wrote %08x; BBPCTL still busy\n",
! 1946: sc->sc_dev.dv_xname, reg);
! 1947: return ETIMEDOUT;
! 1948: }
! 1949: if (val != NULL)
! 1950: *val = MASK_AND_RSHIFT(reg, ATW_BBPCTL_DATA_MASK);
! 1951: return 0;
! 1952: }
! 1953: #endif /* ATW_BBPDEBUG */
! 1954:
! 1955: /* Write a register on the Si4126 RF/IF synthesizer using the registers
! 1956: * provided by the ADM8211 for that purpose.
! 1957: *
! 1958: * val is 18 bits of data, and val is the 4-bit address of the register.
! 1959: *
! 1960: * Return 0 on success.
! 1961: */
! 1962: void
! 1963: atw_si4126_write(struct atw_softc *sc, u_int addr, u_int val)
! 1964: {
! 1965: uint32_t bits, mask, reg;
! 1966: int nbits;
! 1967:
! 1968: if (sc->sc_rev >= ATW_REVISION_BA) {
! 1969: nbits = 24;
! 1970:
! 1971: val &= 0x3ffff;
! 1972: addr &= 0x1f;
! 1973: bits = val | (addr << 18);
! 1974: } else {
! 1975: nbits = 22;
! 1976:
! 1977: KASSERT((addr & ~PRESHIFT(SI4126_TWI_ADDR_MASK)) == 0);
! 1978: KASSERT((val & ~PRESHIFT(SI4126_TWI_DATA_MASK)) == 0);
! 1979:
! 1980: bits = LSHIFT(val, SI4126_TWI_DATA_MASK) |
! 1981: LSHIFT(addr, SI4126_TWI_ADDR_MASK);
! 1982: }
! 1983:
! 1984: reg = ATW_SYNRF_SELSYN;
! 1985: /* reference driver: reset Si4126 serial bus to initial
! 1986: * conditions?
! 1987: */
! 1988: ATW_WRITE(sc, ATW_SYNRF, reg | ATW_SYNRF_LEIF);
! 1989: ATW_WRITE(sc, ATW_SYNRF, reg);
! 1990:
! 1991: for (mask = BIT(nbits - 1); mask != 0; mask >>= 1) {
! 1992: if ((bits & mask) != 0)
! 1993: reg |= ATW_SYNRF_SYNDATA;
! 1994: else
! 1995: reg &= ~ATW_SYNRF_SYNDATA;
! 1996: ATW_WRITE(sc, ATW_SYNRF, reg);
! 1997: ATW_WRITE(sc, ATW_SYNRF, reg | ATW_SYNRF_SYNCLK);
! 1998: ATW_WRITE(sc, ATW_SYNRF, reg);
! 1999: }
! 2000: ATW_WRITE(sc, ATW_SYNRF, reg | ATW_SYNRF_LEIF);
! 2001: ATW_WRITE(sc, ATW_SYNRF, 0x0);
! 2002: }
! 2003:
! 2004: /* Read 18-bit data from the 4-bit address addr in Si4126
! 2005: * RF synthesizer and write the data to *val. Return 0 on success.
! 2006: *
! 2007: * XXX This does not seem to work. The ADM8211 must require more or
! 2008: * different magic to read the chip than to write it.
! 2009: */
! 2010: #ifdef ATW_SYNDEBUG
! 2011: int
! 2012: atw_si4126_read(struct atw_softc *sc, u_int addr, u_int *val)
! 2013: {
! 2014: u_int32_t reg;
! 2015: int i;
! 2016:
! 2017: KASSERT((addr & ~PRESHIFT(SI4126_TWI_ADDR_MASK)) == 0);
! 2018:
! 2019: for (i = 1000; --i >= 0; ) {
! 2020: if (ATW_ISSET(sc, ATW_SYNCTL, ATW_SYNCTL_RD|ATW_SYNCTL_WR) == 0)
! 2021: break;
! 2022: DELAY(100);
! 2023: }
! 2024:
! 2025: if (i < 0) {
! 2026: printf("%s: start atw_si4126_read, SYNCTL busy\n",
! 2027: sc->sc_dev.dv_xname);
! 2028: return ETIMEDOUT;
! 2029: }
! 2030:
! 2031: reg = sc->sc_synctl_rd | LSHIFT(addr, ATW_SYNCTL_DATA_MASK);
! 2032:
! 2033: ATW_WRITE(sc, ATW_SYNCTL, reg);
! 2034:
! 2035: for (i = 1000; --i >= 0; ) {
! 2036: DELAY(100);
! 2037: if (ATW_ISSET(sc, ATW_SYNCTL, ATW_SYNCTL_RD) == 0)
! 2038: break;
! 2039: }
! 2040:
! 2041: ATW_CLR(sc, ATW_SYNCTL, ATW_SYNCTL_RD);
! 2042:
! 2043: if (i < 0) {
! 2044: printf("%s: atw_si4126_read wrote %#08x, SYNCTL still busy\n",
! 2045: sc->sc_dev.dv_xname, reg);
! 2046: return ETIMEDOUT;
! 2047: }
! 2048: if (val != NULL)
! 2049: *val = MASK_AND_RSHIFT(ATW_READ(sc, ATW_SYNCTL),
! 2050: ATW_SYNCTL_DATA_MASK);
! 2051: return 0;
! 2052: }
! 2053: #endif /* ATW_SYNDEBUG */
! 2054:
! 2055: /* XXX is the endianness correct? test. */
! 2056: #define atw_calchash(addr) \
! 2057: (ether_crc32_le((addr), IEEE80211_ADDR_LEN) & BITS(5, 0))
! 2058:
! 2059: /*
! 2060: * atw_filter_setup:
! 2061: *
! 2062: * Set the ADM8211's receive filter.
! 2063: */
! 2064: void
! 2065: atw_filter_setup(struct atw_softc *sc)
! 2066: {
! 2067: struct ieee80211com *ic = &sc->sc_ic;
! 2068: #if defined(__OpenBSD__)
! 2069: struct arpcom *ec = &ic->ic_ac;
! 2070: #else
! 2071: struct ethercom *ec = &ic->ic_ec;
! 2072: #endif
! 2073: struct ifnet *ifp = &sc->sc_ic.ic_if;
! 2074: int hash;
! 2075: u_int32_t hashes[2];
! 2076: struct ether_multi *enm;
! 2077: struct ether_multistep step;
! 2078:
! 2079: /* According to comments in tlp_al981_filter_setup
! 2080: * (dev/ic/tulip.c) the ADMtek AL981 does not like for its
! 2081: * multicast filter to be set while it is running. Hopefully
! 2082: * the ADM8211 is not the same!
! 2083: */
! 2084: if ((ifp->if_flags & IFF_RUNNING) != 0)
! 2085: atw_idle(sc, ATW_NAR_SR);
! 2086:
! 2087: sc->sc_opmode &= ~(ATW_NAR_PR|ATW_NAR_MM);
! 2088:
! 2089: /* XXX in scan mode, do not filter packets. Maybe this is
! 2090: * unnecessary.
! 2091: */
! 2092: if (ic->ic_state == IEEE80211_S_SCAN ||
! 2093: (ifp->if_flags & IFF_PROMISC) != 0) {
! 2094: sc->sc_opmode |= ATW_NAR_PR;
! 2095: goto allmulti;
! 2096: }
! 2097:
! 2098: hashes[0] = hashes[1] = 0x0;
! 2099:
! 2100: /*
! 2101: * Program the 64-bit multicast hash filter.
! 2102: */
! 2103: ETHER_FIRST_MULTI(step, ec, enm);
! 2104: while (enm != NULL) {
! 2105: if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
! 2106: ETHER_ADDR_LEN) != 0)
! 2107: goto allmulti;
! 2108:
! 2109: hash = atw_calchash(enm->enm_addrlo);
! 2110: hashes[hash >> 5] |= 1 << (hash & 0x1f);
! 2111: ETHER_NEXT_MULTI(step, enm);
! 2112: sc->sc_opmode |= ATW_NAR_MM;
! 2113: }
! 2114: ifp->if_flags &= ~IFF_ALLMULTI;
! 2115: goto setit;
! 2116:
! 2117: allmulti:
! 2118: sc->sc_opmode |= ATW_NAR_MM;
! 2119: ifp->if_flags |= IFF_ALLMULTI;
! 2120: hashes[0] = hashes[1] = 0xffffffff;
! 2121:
! 2122: setit:
! 2123: ATW_WRITE(sc, ATW_MAR0, hashes[0]);
! 2124: ATW_WRITE(sc, ATW_MAR1, hashes[1]);
! 2125: ATW_WRITE(sc, ATW_NAR, sc->sc_opmode);
! 2126: DELAY(20 * 1000);
! 2127: ATW_WRITE(sc, ATW_RDR, 0x1);
! 2128:
! 2129: DPRINTF(sc, ("%s: ATW_NAR %08x opmode %08x\n", sc->sc_dev.dv_xname,
! 2130: ATW_READ(sc, ATW_NAR), sc->sc_opmode));
! 2131: }
! 2132:
! 2133: /* Tell the ADM8211 our preferred BSSID. The ADM8211 must match
! 2134: * a beacon's BSSID and SSID against the preferred BSSID and SSID
! 2135: * before it will raise ATW_INTR_LINKON. When the ADM8211 receives
! 2136: * no beacon with the preferred BSSID and SSID in the number of
! 2137: * beacon intervals given in ATW_BPLI, then it raises ATW_INTR_LINKOFF.
! 2138: */
! 2139: void
! 2140: atw_write_bssid(struct atw_softc *sc)
! 2141: {
! 2142: struct ieee80211com *ic = &sc->sc_ic;
! 2143: u_int8_t *bssid;
! 2144:
! 2145: bssid = ic->ic_bss->ni_bssid;
! 2146:
! 2147: ATW_WRITE(sc, ATW_BSSID0,
! 2148: LSHIFT(bssid[0], ATW_BSSID0_BSSIDB0_MASK) |
! 2149: LSHIFT(bssid[1], ATW_BSSID0_BSSIDB1_MASK) |
! 2150: LSHIFT(bssid[2], ATW_BSSID0_BSSIDB2_MASK) |
! 2151: LSHIFT(bssid[3], ATW_BSSID0_BSSIDB3_MASK));
! 2152:
! 2153: ATW_WRITE(sc, ATW_ABDA1,
! 2154: (ATW_READ(sc, ATW_ABDA1) &
! 2155: ~(ATW_ABDA1_BSSIDB4_MASK|ATW_ABDA1_BSSIDB5_MASK)) |
! 2156: LSHIFT(bssid[4], ATW_ABDA1_BSSIDB4_MASK) |
! 2157: LSHIFT(bssid[5], ATW_ABDA1_BSSIDB5_MASK));
! 2158:
! 2159: DPRINTF(sc, ("%s: BSSID %s -> ", sc->sc_dev.dv_xname,
! 2160: ether_sprintf(sc->sc_bssid)));
! 2161: DPRINTF(sc, ("%s\n", ether_sprintf(bssid)));
! 2162:
! 2163: memcpy(sc->sc_bssid, bssid, sizeof(sc->sc_bssid));
! 2164: }
! 2165:
! 2166: /* Write buflen bytes from buf to SRAM starting at the SRAM's ofs'th
! 2167: * 16-bit word.
! 2168: */
! 2169: void
! 2170: atw_write_sram(struct atw_softc *sc, u_int ofs, u_int8_t *buf, u_int buflen)
! 2171: {
! 2172: u_int i;
! 2173: u_int8_t *ptr;
! 2174:
! 2175: memcpy(&sc->sc_sram[ofs], buf, buflen);
! 2176:
! 2177: KASSERT(ofs % 2 == 0 && buflen % 2 == 0);
! 2178:
! 2179: KASSERT(buflen + ofs <= sc->sc_sramlen);
! 2180:
! 2181: ptr = &sc->sc_sram[ofs];
! 2182:
! 2183: for (i = 0; i < buflen; i += 2) {
! 2184: ATW_WRITE(sc, ATW_WEPCTL, ATW_WEPCTL_WR |
! 2185: LSHIFT((ofs + i) / 2, ATW_WEPCTL_TBLADD_MASK));
! 2186: DELAY(atw_writewep_delay);
! 2187:
! 2188: ATW_WRITE(sc, ATW_WESK,
! 2189: LSHIFT((ptr[i + 1] << 8) | ptr[i], ATW_WESK_DATA_MASK));
! 2190: DELAY(atw_writewep_delay);
! 2191: }
! 2192: ATW_WRITE(sc, ATW_WEPCTL, sc->sc_wepctl); /* restore WEP condition */
! 2193:
! 2194: if (sc->sc_if.if_flags & IFF_DEBUG) {
! 2195: int n_octets = 0;
! 2196: printf("%s: wrote %d bytes at 0x%x wepctl 0x%08x\n",
! 2197: sc->sc_dev.dv_xname, buflen, ofs, sc->sc_wepctl);
! 2198: for (i = 0; i < buflen; i++) {
! 2199: printf(" %02x", ptr[i]);
! 2200: if (++n_octets % 24 == 0)
! 2201: printf("\n");
! 2202: }
! 2203: if (n_octets % 24 != 0)
! 2204: printf("\n");
! 2205: }
! 2206: }
! 2207:
! 2208: /* Write WEP keys from the ieee80211com to the ADM8211's SRAM. */
! 2209: void
! 2210: atw_write_wep(struct atw_softc *sc)
! 2211: {
! 2212: struct ieee80211com *ic = &sc->sc_ic;
! 2213: #if 0
! 2214: u_int32_t reg;
! 2215: int i;
! 2216: #endif
! 2217: /* SRAM shared-key record format: key0 flags key1 ... key12 */
! 2218: u_int8_t buf[IEEE80211_WEP_NKID]
! 2219: [1 /* key[0] */ + 1 /* flags */ + 12 /* key[1 .. 12] */];
! 2220:
! 2221: sc->sc_wepctl = 0;
! 2222: ATW_WRITE(sc, ATW_WEPCTL, sc->sc_wepctl);
! 2223:
! 2224: if ((ic->ic_flags & IEEE80211_F_WEPON) == 0)
! 2225: return;
! 2226:
! 2227: memset(&buf[0][0], 0, sizeof(buf));
! 2228:
! 2229: #if 0
! 2230: for (i = 0; i < IEEE80211_WEP_NKID; i++) {
! 2231: if (ic->ic_nw_keys[i].k_len > 5) {
! 2232: buf[i][1] = ATW_WEP_ENABLED | ATW_WEP_104BIT;
! 2233: } else if (ic->ic_nw_keys[i].k_len != 0) {
! 2234: buf[i][1] = ATW_WEP_ENABLED;
! 2235: } else {
! 2236: buf[i][1] = 0;
! 2237: continue;
! 2238: }
! 2239: buf[i][0] = ic->ic_nw_keys[i].k_key[0];
! 2240: memcpy(&buf[i][2], &ic->ic_nw_keys[i].k_key[1],
! 2241: ic->ic_nw_keys[i].k_len - 1);
! 2242: }
! 2243:
! 2244: reg = ATW_READ(sc, ATW_MACTEST);
! 2245: reg |= ATW_MACTEST_MMI_USETXCLK | ATW_MACTEST_FORCE_KEYID;
! 2246: reg &= ~ATW_MACTEST_KEYID_MASK;
! 2247: reg |= LSHIFT(ic->ic_wep_txkey, ATW_MACTEST_KEYID_MASK);
! 2248: ATW_WRITE(sc, ATW_MACTEST, reg);
! 2249:
! 2250: sc->sc_wepctl = ATW_WEPCTL_WEPENABLE;
! 2251:
! 2252: switch (sc->sc_rev) {
! 2253: case ATW_REVISION_AB:
! 2254: case ATW_REVISION_AF:
! 2255: /* Bypass WEP on Rx. */
! 2256: sc->sc_wepctl |= ATW_WEPCTL_WEPRXBYP;
! 2257: break;
! 2258: default:
! 2259: break;
! 2260: }
! 2261: #endif
! 2262:
! 2263: atw_write_sram(sc, ATW_SRAM_ADDR_SHARED_KEY, (u_int8_t*)&buf[0][0],
! 2264: sizeof(buf));
! 2265: }
! 2266:
! 2267: void
! 2268: atw_change_ibss(struct atw_softc *sc)
! 2269: {
! 2270: atw_predict_beacon(sc);
! 2271: atw_write_bssid(sc);
! 2272: atw_start_beacon(sc, 1);
! 2273: }
! 2274:
! 2275: void
! 2276: atw_recv_mgmt(struct ieee80211com *ic, struct mbuf *m,
! 2277: struct ieee80211_node *ni, int subtype, int rssi, u_int32_t rstamp)
! 2278: {
! 2279: struct atw_softc *sc = (struct atw_softc*)ic->ic_softc;
! 2280:
! 2281: /* The ADM8211A answers probe requests. */
! 2282: if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_REQ &&
! 2283: sc->sc_rev < ATW_REVISION_BA)
! 2284: return;
! 2285:
! 2286: (*sc->sc_recv_mgmt)(ic, m, ni, subtype, rssi, rstamp);
! 2287:
! 2288: switch (subtype) {
! 2289: case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
! 2290: case IEEE80211_FC0_SUBTYPE_BEACON:
! 2291: if (ic->ic_opmode != IEEE80211_M_IBSS ||
! 2292: ic->ic_state != IEEE80211_S_RUN)
! 2293: break;
! 2294: if (ieee80211_ibss_merge(ic, ni, atw_get_tsft(sc)) == ENETRESET)
! 2295: atw_change_ibss(sc);
! 2296: break;
! 2297: default:
! 2298: break;
! 2299: }
! 2300: return;
! 2301: }
! 2302:
! 2303: /* Write the SSID in the ieee80211com to the SRAM on the ADM8211.
! 2304: * In ad hoc mode, the SSID is written to the beacons sent by the
! 2305: * ADM8211. In both ad hoc and infrastructure mode, beacons received
! 2306: * with matching SSID affect ATW_INTR_LINKON/ATW_INTR_LINKOFF
! 2307: * indications.
! 2308: */
! 2309: void
! 2310: atw_write_ssid(struct atw_softc *sc)
! 2311: {
! 2312: struct ieee80211com *ic = &sc->sc_ic;
! 2313: /* 34 bytes are reserved in ADM8211 SRAM for the SSID, but
! 2314: * it only expects the element length, not its ID.
! 2315: */
! 2316: u_int8_t buf[roundup(1 /* length */ + IEEE80211_NWID_LEN, 2)];
! 2317:
! 2318: memset(buf, 0, sizeof(buf));
! 2319: buf[0] = ic->ic_bss->ni_esslen;
! 2320: memcpy(&buf[1], ic->ic_bss->ni_essid, ic->ic_bss->ni_esslen);
! 2321:
! 2322: atw_write_sram(sc, ATW_SRAM_ADDR_SSID, buf,
! 2323: roundup(1 + ic->ic_bss->ni_esslen, 2));
! 2324: }
! 2325:
! 2326: /* Write the supported rates in the ieee80211com to the SRAM of the ADM8211.
! 2327: * In ad hoc mode, the supported rates are written to beacons sent by the
! 2328: * ADM8211.
! 2329: */
! 2330: void
! 2331: atw_write_sup_rates(struct atw_softc *sc)
! 2332: {
! 2333: struct ieee80211com *ic = &sc->sc_ic;
! 2334: /* 14 bytes are probably (XXX) reserved in the ADM8211 SRAM for
! 2335: * supported rates
! 2336: */
! 2337: u_int8_t buf[roundup(1 /* length */ + IEEE80211_RATE_SIZE, 2)];
! 2338:
! 2339: memset(buf, 0, sizeof(buf));
! 2340: buf[0] = ic->ic_bss->ni_rates.rs_nrates;
! 2341: memcpy(&buf[1], ic->ic_bss->ni_rates.rs_rates,
! 2342: ic->ic_bss->ni_rates.rs_nrates);
! 2343:
! 2344: /* XXX deal with rev BA bug linux driver talks of? */
! 2345:
! 2346: atw_write_sram(sc, ATW_SRAM_ADDR_SUPRATES, buf, sizeof(buf));
! 2347: }
! 2348:
! 2349: /* Start/stop sending beacons. */
! 2350: void
! 2351: atw_start_beacon(struct atw_softc *sc, int start)
! 2352: {
! 2353: struct ieee80211com *ic = &sc->sc_ic;
! 2354: uint16_t chan;
! 2355: uint32_t bcnt, bpli, cap0, cap1, capinfo;
! 2356: size_t len;
! 2357:
! 2358: if (ATW_IS_ENABLED(sc) == 0)
! 2359: return;
! 2360:
! 2361: /* start beacons */
! 2362: len = sizeof(struct ieee80211_frame) +
! 2363: 8 /* timestamp */ + 2 /* beacon interval */ +
! 2364: 2 /* capability info */ +
! 2365: 2 + ic->ic_bss->ni_esslen /* SSID element */ +
! 2366: 2 + ic->ic_bss->ni_rates.rs_nrates /* rates element */ +
! 2367: 3 /* DS parameters */ +
! 2368: IEEE80211_CRC_LEN;
! 2369:
! 2370: bcnt = ATW_READ(sc, ATW_BCNT) & ~ATW_BCNT_BCNT_MASK;
! 2371: cap0 = ATW_READ(sc, ATW_CAP0) & ~ATW_CAP0_CHN_MASK;
! 2372: cap1 = ATW_READ(sc, ATW_CAP1) & ~ATW_CAP1_CAPI_MASK;
! 2373:
! 2374: ATW_WRITE(sc, ATW_BCNT, bcnt);
! 2375: ATW_WRITE(sc, ATW_CAP1, cap1);
! 2376:
! 2377: if (!start)
! 2378: return;
! 2379:
! 2380: /* TBD use ni_capinfo */
! 2381:
! 2382: capinfo = 0;
! 2383: if (sc->sc_flags & ATWF_SHORT_PREAMBLE)
! 2384: capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
! 2385: if (ic->ic_flags & IEEE80211_F_WEPON)
! 2386: capinfo |= IEEE80211_CAPINFO_PRIVACY;
! 2387:
! 2388: switch (ic->ic_opmode) {
! 2389: case IEEE80211_M_IBSS:
! 2390: len += 4; /* IBSS parameters */
! 2391: capinfo |= IEEE80211_CAPINFO_IBSS;
! 2392: break;
! 2393: case IEEE80211_M_HOSTAP:
! 2394: /* XXX 6-byte minimum TIM */
! 2395: len += atw_beacon_len_adjust;
! 2396: capinfo |= IEEE80211_CAPINFO_ESS;
! 2397: break;
! 2398: default:
! 2399: return;
! 2400: }
! 2401:
! 2402: /* set listen interval
! 2403: * XXX do software units agree w/ hardware?
! 2404: */
! 2405: bpli = LSHIFT(ic->ic_bss->ni_intval, ATW_BPLI_BP_MASK) |
! 2406: LSHIFT(ic->ic_lintval / ic->ic_bss->ni_intval, ATW_BPLI_LI_MASK);
! 2407:
! 2408: chan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
! 2409:
! 2410: bcnt |= LSHIFT(len, ATW_BCNT_BCNT_MASK);
! 2411: cap0 |= LSHIFT(chan, ATW_CAP0_CHN_MASK);
! 2412: cap1 |= LSHIFT(capinfo, ATW_CAP1_CAPI_MASK);
! 2413:
! 2414: ATW_WRITE(sc, ATW_BCNT, bcnt);
! 2415: ATW_WRITE(sc, ATW_BPLI, bpli);
! 2416: ATW_WRITE(sc, ATW_CAP0, cap0);
! 2417: ATW_WRITE(sc, ATW_CAP1, cap1);
! 2418:
! 2419: DPRINTF(sc, ("%s: atw_start_beacon reg[ATW_BCNT] = %08x\n",
! 2420: sc->sc_dev.dv_xname, bcnt));
! 2421: DPRINTF(sc, ("%s: atw_start_beacon reg[ATW_CAP1] = %08x\n",
! 2422: sc->sc_dev.dv_xname, cap1));
! 2423: }
! 2424:
! 2425: /* Return the 32 lsb of the last TSFT divisible by ival. */
! 2426: static __inline uint32_t
! 2427: atw_last_even_tsft(uint32_t tsfth, uint32_t tsftl, uint32_t ival)
! 2428: {
! 2429: /* Following the reference driver's lead, I compute
! 2430: *
! 2431: * (uint32_t)((((uint64_t)tsfth << 32) | tsftl) % ival)
! 2432: *
! 2433: * without using 64-bit arithmetic, using the following
! 2434: * relationship:
! 2435: *
! 2436: * (0x100000000 * H + L) % m
! 2437: * = ((0x100000000 % m) * H + L) % m
! 2438: * = (((0xffffffff + 1) % m) * H + L) % m
! 2439: * = ((0xffffffff % m + 1 % m) * H + L) % m
! 2440: * = ((0xffffffff % m + 1) * H + L) % m
! 2441: */
! 2442: return ((0xFFFFFFFF % ival + 1) * tsfth + tsftl) % ival;
! 2443: }
! 2444:
! 2445: uint64_t
! 2446: atw_get_tsft(struct atw_softc *sc)
! 2447: {
! 2448: int i;
! 2449: uint32_t tsfth, tsftl;
! 2450: for (i = 0; i < 2; i++) {
! 2451: tsfth = ATW_READ(sc, ATW_TSFTH);
! 2452: tsftl = ATW_READ(sc, ATW_TSFTL);
! 2453: if (ATW_READ(sc, ATW_TSFTH) == tsfth)
! 2454: break;
! 2455: }
! 2456: return ((uint64_t)tsfth << 32) | tsftl;
! 2457: }
! 2458:
! 2459: /* If we've created an IBSS, write the TSF time in the ADM8211 to
! 2460: * the ieee80211com.
! 2461: *
! 2462: * Predict the next target beacon transmission time (TBTT) and
! 2463: * write it to the ADM8211.
! 2464: */
! 2465: void
! 2466: atw_predict_beacon(struct atw_softc *sc)
! 2467: {
! 2468: #define TBTTOFS 20 /* TU */
! 2469:
! 2470: struct ieee80211com *ic = &sc->sc_ic;
! 2471: uint64_t tsft;
! 2472: uint32_t ival, past_even, tbtt, tsfth, tsftl;
! 2473: union {
! 2474: uint64_t word;
! 2475: uint8_t tstamp[8];
! 2476: } u;
! 2477:
! 2478: if ((ic->ic_opmode == IEEE80211_M_HOSTAP) ||
! 2479: ((ic->ic_opmode == IEEE80211_M_IBSS) &&
! 2480: (ic->ic_flags & IEEE80211_F_SIBSS))) {
! 2481: tsft = atw_get_tsft(sc);
! 2482: u.word = htole64(tsft);
! 2483: (void)memcpy(&ic->ic_bss->ni_tstamp[0], &u.tstamp[0],
! 2484: sizeof(ic->ic_bss->ni_tstamp));
! 2485: } else {
! 2486: (void)memcpy(&u, &ic->ic_bss->ni_tstamp[0], sizeof(u));
! 2487: tsft = letoh64(u.word);
! 2488: }
! 2489:
! 2490: ival = ic->ic_bss->ni_intval * IEEE80211_DUR_TU;
! 2491:
! 2492: tsftl = tsft & 0xFFFFFFFF;
! 2493: tsfth = tsft >> 32;
! 2494:
! 2495: /* We sent/received the last beacon `past' microseconds
! 2496: * after the interval divided the TSF timer.
! 2497: */
! 2498: past_even = tsftl - atw_last_even_tsft(tsfth, tsftl, ival);
! 2499:
! 2500: /* Skip ten beacons so that the TBTT cannot pass before
! 2501: * we've programmed it. Ten is an arbitrary number.
! 2502: */
! 2503: tbtt = past_even + ival * 10;
! 2504:
! 2505: ATW_WRITE(sc, ATW_TOFS1,
! 2506: LSHIFT(1, ATW_TOFS1_TSFTOFSR_MASK) |
! 2507: LSHIFT(TBTTOFS, ATW_TOFS1_TBTTOFS_MASK) |
! 2508: LSHIFT(MASK_AND_RSHIFT(tbtt - TBTTOFS * IEEE80211_DUR_TU,
! 2509: ATW_TBTTPRE_MASK), ATW_TOFS1_TBTTPRE_MASK));
! 2510: #undef TBTTOFS
! 2511: }
! 2512:
! 2513: void
! 2514: atw_next_scan(void *arg)
! 2515: {
! 2516: struct atw_softc *sc = arg;
! 2517: struct ieee80211com *ic = &sc->sc_ic;
! 2518: struct ifnet *ifp = &ic->ic_if;
! 2519: int s;
! 2520:
! 2521: /* don't call atw_start w/o network interrupts blocked */
! 2522: s = splnet();
! 2523: if (ic->ic_state == IEEE80211_S_SCAN)
! 2524: ieee80211_next_scan(ifp);
! 2525: splx(s);
! 2526: }
! 2527:
! 2528: /* Synchronize the hardware state with the software state. */
! 2529: int
! 2530: atw_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
! 2531: {
! 2532: struct ifnet *ifp = &ic->ic_if;
! 2533: struct atw_softc *sc = ifp->if_softc;
! 2534: enum ieee80211_state ostate = ic->ic_state;
! 2535: int error;
! 2536:
! 2537: if (nstate == IEEE80211_S_INIT) {
! 2538: timeout_del(&sc->sc_scan_to);
! 2539: sc->sc_cur_chan = IEEE80211_CHAN_ANY;
! 2540: atw_start_beacon(sc, 0);
! 2541: return (*sc->sc_newstate)(ic, nstate, arg);
! 2542: }
! 2543:
! 2544: if ((error = atw_tune(sc)) != 0)
! 2545: return error;
! 2546:
! 2547: switch (nstate) {
! 2548: case IEEE80211_S_ASSOC:
! 2549: break;
! 2550: case IEEE80211_S_INIT:
! 2551: panic("%s: unexpected state IEEE80211_S_INIT", __func__);
! 2552: break;
! 2553: case IEEE80211_S_SCAN:
! 2554: timeout_add(&sc->sc_scan_to, atw_dwelltime * hz / 1000);
! 2555: break;
! 2556: case IEEE80211_S_RUN:
! 2557: if (ic->ic_opmode == IEEE80211_M_STA)
! 2558: break;
! 2559: /*FALLTHROUGH*/
! 2560: case IEEE80211_S_AUTH:
! 2561: atw_write_bssid(sc);
! 2562: atw_write_ssid(sc);
! 2563: atw_write_sup_rates(sc);
! 2564:
! 2565: if (ic->ic_opmode == IEEE80211_M_AHDEMO ||
! 2566: ic->ic_opmode == IEEE80211_M_MONITOR)
! 2567: break;
! 2568:
! 2569: /* set listen interval
! 2570: * XXX do software units agree w/ hardware?
! 2571: */
! 2572: ATW_WRITE(sc, ATW_BPLI,
! 2573: LSHIFT(ic->ic_bss->ni_intval, ATW_BPLI_BP_MASK) |
! 2574: LSHIFT(ic->ic_lintval / ic->ic_bss->ni_intval,
! 2575: ATW_BPLI_LI_MASK));
! 2576:
! 2577: DPRINTF(sc, ("%s: reg[ATW_BPLI] = %08x\n",
! 2578: sc->sc_dev.dv_xname, ATW_READ(sc, ATW_BPLI)));
! 2579:
! 2580: atw_predict_beacon(sc);
! 2581: break;
! 2582: }
! 2583:
! 2584: if (nstate != IEEE80211_S_SCAN)
! 2585: timeout_del(&sc->sc_scan_to);
! 2586:
! 2587: if (nstate == IEEE80211_S_RUN &&
! 2588: (ic->ic_opmode == IEEE80211_M_HOSTAP ||
! 2589: ic->ic_opmode == IEEE80211_M_IBSS))
! 2590: atw_start_beacon(sc, 1);
! 2591: else
! 2592: atw_start_beacon(sc, 0);
! 2593:
! 2594: error = (*sc->sc_newstate)(ic, nstate, arg);
! 2595:
! 2596: if (ostate == IEEE80211_S_INIT && nstate == IEEE80211_S_SCAN)
! 2597: atw_write_bssid(sc);
! 2598:
! 2599: return error;
! 2600: }
! 2601:
! 2602: /*
! 2603: * atw_add_rxbuf:
! 2604: *
! 2605: * Add a receive buffer to the indicated descriptor.
! 2606: */
! 2607: int
! 2608: atw_add_rxbuf(struct atw_softc *sc, int idx)
! 2609: {
! 2610: struct atw_rxsoft *rxs = &sc->sc_rxsoft[idx];
! 2611: struct mbuf *m;
! 2612: int error;
! 2613:
! 2614: MGETHDR(m, M_DONTWAIT, MT_DATA);
! 2615: if (m == NULL)
! 2616: return (ENOBUFS);
! 2617:
! 2618: MCLGET(m, M_DONTWAIT);
! 2619: if ((m->m_flags & M_EXT) == 0) {
! 2620: m_freem(m);
! 2621: return (ENOBUFS);
! 2622: }
! 2623:
! 2624: if (rxs->rxs_mbuf != NULL)
! 2625: bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap);
! 2626:
! 2627: rxs->rxs_mbuf = m;
! 2628:
! 2629: error = bus_dmamap_load(sc->sc_dmat, rxs->rxs_dmamap,
! 2630: m->m_ext.ext_buf, m->m_ext.ext_size, NULL,
! 2631: BUS_DMA_READ|BUS_DMA_NOWAIT);
! 2632: if (error) {
! 2633: printf("%s: can't load rx DMA map %d, error = %d\n",
! 2634: sc->sc_dev.dv_xname, idx, error);
! 2635: panic("atw_add_rxbuf"); /* XXX */
! 2636: }
! 2637:
! 2638: bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
! 2639: rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
! 2640:
! 2641: ATW_INIT_RXDESC(sc, idx);
! 2642:
! 2643: return (0);
! 2644: }
! 2645:
! 2646: /*
! 2647: * Release any queued transmit buffers.
! 2648: */
! 2649: void
! 2650: atw_txdrain(struct atw_softc *sc)
! 2651: {
! 2652: struct atw_txsoft *txs;
! 2653:
! 2654: while ((txs = SIMPLEQ_FIRST(&sc->sc_txdirtyq)) != NULL) {
! 2655: SIMPLEQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q);
! 2656: if (txs->txs_mbuf != NULL) {
! 2657: bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap);
! 2658: m_freem(txs->txs_mbuf);
! 2659: txs->txs_mbuf = NULL;
! 2660: }
! 2661: SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
! 2662: }
! 2663: sc->sc_tx_timer = 0;
! 2664: }
! 2665:
! 2666: /*
! 2667: * atw_stop: [ ifnet interface function ]
! 2668: *
! 2669: * Stop transmission on the interface.
! 2670: */
! 2671: void
! 2672: atw_stop(struct ifnet *ifp, int disable)
! 2673: {
! 2674: struct atw_softc *sc = ifp->if_softc;
! 2675: struct ieee80211com *ic = &sc->sc_ic;
! 2676:
! 2677: ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
! 2678:
! 2679: /*
! 2680: * Mark the interface down and cancel the watchdog timer.
! 2681: */
! 2682: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
! 2683: ifp->if_timer = 0;
! 2684:
! 2685: /* Disable interrupts. */
! 2686: ATW_WRITE(sc, ATW_IER, 0);
! 2687:
! 2688: /* Stop the transmit and receive processes. */
! 2689: sc->sc_opmode = 0;
! 2690: ATW_WRITE(sc, ATW_NAR, 0);
! 2691: DELAY(20 * 1000);
! 2692: ATW_WRITE(sc, ATW_TDBD, 0);
! 2693: ATW_WRITE(sc, ATW_TDBP, 0);
! 2694: ATW_WRITE(sc, ATW_RDB, 0);
! 2695:
! 2696: atw_txdrain(sc);
! 2697:
! 2698: if (disable) {
! 2699: atw_rxdrain(sc);
! 2700: atw_disable(sc);
! 2701: }
! 2702:
! 2703: if (!disable)
! 2704: atw_reset(sc);
! 2705: }
! 2706:
! 2707: /*
! 2708: * atw_rxdrain:
! 2709: *
! 2710: * Drain the receive queue.
! 2711: */
! 2712: void
! 2713: atw_rxdrain(struct atw_softc *sc)
! 2714: {
! 2715: struct atw_rxsoft *rxs;
! 2716: int i;
! 2717:
! 2718: for (i = 0; i < ATW_NRXDESC; i++) {
! 2719: rxs = &sc->sc_rxsoft[i];
! 2720: if (rxs->rxs_mbuf == NULL)
! 2721: continue;
! 2722: bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap);
! 2723: m_freem(rxs->rxs_mbuf);
! 2724: rxs->rxs_mbuf = NULL;
! 2725: }
! 2726: }
! 2727:
! 2728: /*
! 2729: * atw_detach:
! 2730: *
! 2731: * Detach an ADM8211 interface.
! 2732: */
! 2733: int
! 2734: atw_detach(struct atw_softc *sc)
! 2735: {
! 2736: struct ifnet *ifp = &sc->sc_ic.ic_if;
! 2737: struct atw_rxsoft *rxs;
! 2738: struct atw_txsoft *txs;
! 2739: int i;
! 2740:
! 2741: /*
! 2742: * Succeed now if there isn't any work to do.
! 2743: */
! 2744: if ((sc->sc_flags & ATWF_ATTACHED) == 0)
! 2745: return (0);
! 2746:
! 2747: timeout_del(&sc->sc_scan_to);
! 2748:
! 2749: ieee80211_ifdetach(ifp);
! 2750: if_detach(ifp);
! 2751:
! 2752: for (i = 0; i < ATW_NRXDESC; i++) {
! 2753: rxs = &sc->sc_rxsoft[i];
! 2754: if (rxs->rxs_mbuf != NULL) {
! 2755: bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap);
! 2756: m_freem(rxs->rxs_mbuf);
! 2757: rxs->rxs_mbuf = NULL;
! 2758: }
! 2759: bus_dmamap_destroy(sc->sc_dmat, rxs->rxs_dmamap);
! 2760: }
! 2761: for (i = 0; i < ATW_TXQUEUELEN; i++) {
! 2762: txs = &sc->sc_txsoft[i];
! 2763: if (txs->txs_mbuf != NULL) {
! 2764: bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap);
! 2765: m_freem(txs->txs_mbuf);
! 2766: txs->txs_mbuf = NULL;
! 2767: }
! 2768: bus_dmamap_destroy(sc->sc_dmat, txs->txs_dmamap);
! 2769: }
! 2770: bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap);
! 2771: bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap);
! 2772: bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_control_data,
! 2773: sizeof(struct atw_control_data));
! 2774: bus_dmamem_free(sc->sc_dmat, &sc->sc_cdseg, sc->sc_cdnseg);
! 2775:
! 2776: if (sc->sc_sdhook != NULL)
! 2777: shutdownhook_disestablish(sc->sc_sdhook);
! 2778: if (sc->sc_powerhook != NULL)
! 2779: powerhook_disestablish(sc->sc_powerhook);
! 2780:
! 2781: if (sc->sc_srom)
! 2782: free(sc->sc_srom, M_DEVBUF);
! 2783:
! 2784: return (0);
! 2785: }
! 2786:
! 2787: /* atw_shutdown: make sure the interface is stopped at reboot time. */
! 2788: void
! 2789: atw_shutdown(void *arg)
! 2790: {
! 2791: struct atw_softc *sc = arg;
! 2792:
! 2793: atw_stop(&sc->sc_ic.ic_if, 1);
! 2794: }
! 2795:
! 2796: int
! 2797: atw_intr(void *arg)
! 2798: {
! 2799: struct atw_softc *sc = arg;
! 2800: struct ifnet *ifp = &sc->sc_ic.ic_if;
! 2801: u_int32_t status, rxstatus, txstatus, linkstatus;
! 2802: int handled = 0, txthresh;
! 2803:
! 2804: #ifdef DEBUG
! 2805: if (ATW_IS_ENABLED(sc) == 0)
! 2806: panic("%s: atw_intr: not enabled", sc->sc_dev.dv_xname);
! 2807: #endif
! 2808:
! 2809: /*
! 2810: * If the interface isn't running, the interrupt couldn't
! 2811: * possibly have come from us.
! 2812: */
! 2813: if ((ifp->if_flags & IFF_RUNNING) == 0 ||
! 2814: (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
! 2815: return (0);
! 2816:
! 2817: for (;;) {
! 2818: status = ATW_READ(sc, ATW_STSR);
! 2819:
! 2820: if (status)
! 2821: ATW_WRITE(sc, ATW_STSR, status);
! 2822:
! 2823: #ifdef ATW_DEBUG
! 2824: #define PRINTINTR(flag) do { \
! 2825: if ((status & flag) != 0) { \
! 2826: printf("%s" #flag, delim); \
! 2827: delim = ","; \
! 2828: } \
! 2829: } while (0)
! 2830:
! 2831: if (atw_debug > 1 && status) {
! 2832: const char *delim = "<";
! 2833:
! 2834: printf("%s: reg[STSR] = %x",
! 2835: sc->sc_dev.dv_xname, status);
! 2836:
! 2837: PRINTINTR(ATW_INTR_FBE);
! 2838: PRINTINTR(ATW_INTR_LINKOFF);
! 2839: PRINTINTR(ATW_INTR_LINKON);
! 2840: PRINTINTR(ATW_INTR_RCI);
! 2841: PRINTINTR(ATW_INTR_RDU);
! 2842: PRINTINTR(ATW_INTR_REIS);
! 2843: PRINTINTR(ATW_INTR_RPS);
! 2844: PRINTINTR(ATW_INTR_TCI);
! 2845: PRINTINTR(ATW_INTR_TDU);
! 2846: PRINTINTR(ATW_INTR_TLT);
! 2847: PRINTINTR(ATW_INTR_TPS);
! 2848: PRINTINTR(ATW_INTR_TRT);
! 2849: PRINTINTR(ATW_INTR_TUF);
! 2850: PRINTINTR(ATW_INTR_BCNTC);
! 2851: PRINTINTR(ATW_INTR_ATIME);
! 2852: PRINTINTR(ATW_INTR_TBTT);
! 2853: PRINTINTR(ATW_INTR_TSCZ);
! 2854: PRINTINTR(ATW_INTR_TSFTF);
! 2855: printf(">\n");
! 2856: }
! 2857: #undef PRINTINTR
! 2858: #endif /* ATW_DEBUG */
! 2859:
! 2860: if ((status & sc->sc_inten) == 0)
! 2861: break;
! 2862:
! 2863: handled = 1;
! 2864:
! 2865: rxstatus = status & sc->sc_rxint_mask;
! 2866: txstatus = status & sc->sc_txint_mask;
! 2867: linkstatus = status & sc->sc_linkint_mask;
! 2868:
! 2869: if (linkstatus) {
! 2870: atw_linkintr(sc, linkstatus);
! 2871: }
! 2872:
! 2873: if (rxstatus) {
! 2874: /* Grab any new packets. */
! 2875: atw_rxintr(sc);
! 2876:
! 2877: if (rxstatus & ATW_INTR_RDU) {
! 2878: printf("%s: receive ring overrun\n",
! 2879: sc->sc_dev.dv_xname);
! 2880: /* Get the receive process going again. */
! 2881: ATW_WRITE(sc, ATW_RDR, 0x1);
! 2882: break;
! 2883: }
! 2884: }
! 2885:
! 2886: if (txstatus) {
! 2887: /* Sweep up transmit descriptors. */
! 2888: atw_txintr(sc);
! 2889:
! 2890: if (txstatus & ATW_INTR_TLT)
! 2891: DPRINTF(sc, ("%s: tx lifetime exceeded\n",
! 2892: sc->sc_dev.dv_xname));
! 2893:
! 2894: if (txstatus & ATW_INTR_TRT)
! 2895: DPRINTF(sc, ("%s: tx retry limit exceeded\n",
! 2896: sc->sc_dev.dv_xname));
! 2897:
! 2898: /* If Tx under-run, increase our transmit threshold
! 2899: * if another is available.
! 2900: */
! 2901: txthresh = sc->sc_txthresh + 1;
! 2902: if ((txstatus & ATW_INTR_TUF) &&
! 2903: sc->sc_txth[txthresh].txth_name != NULL) {
! 2904: /* Idle the transmit process. */
! 2905: atw_idle(sc, ATW_NAR_ST);
! 2906:
! 2907: sc->sc_txthresh = txthresh;
! 2908: sc->sc_opmode &= ~(ATW_NAR_TR_MASK|ATW_NAR_SF);
! 2909: sc->sc_opmode |=
! 2910: sc->sc_txth[txthresh].txth_opmode;
! 2911: printf("%s: transmit underrun; new "
! 2912: "threshold: %s\n", sc->sc_dev.dv_xname,
! 2913: sc->sc_txth[txthresh].txth_name);
! 2914:
! 2915: /* Set the new threshold and restart
! 2916: * the transmit process.
! 2917: */
! 2918: ATW_WRITE(sc, ATW_NAR, sc->sc_opmode);
! 2919: DELAY(20 * 1000);
! 2920: ATW_WRITE(sc, ATW_RDR, 0x1);
! 2921: /* XXX Log every Nth underrun from
! 2922: * XXX now on?
! 2923: */
! 2924: }
! 2925: }
! 2926:
! 2927: if (status & (ATW_INTR_TPS|ATW_INTR_RPS)) {
! 2928: if (status & ATW_INTR_TPS)
! 2929: printf("%s: transmit process stopped\n",
! 2930: sc->sc_dev.dv_xname);
! 2931: if (status & ATW_INTR_RPS)
! 2932: printf("%s: receive process stopped\n",
! 2933: sc->sc_dev.dv_xname);
! 2934: (void)atw_init(ifp);
! 2935: break;
! 2936: }
! 2937:
! 2938: if (status & ATW_INTR_FBE) {
! 2939: printf("%s: fatal bus error\n", sc->sc_dev.dv_xname);
! 2940: (void)atw_init(ifp);
! 2941: break;
! 2942: }
! 2943:
! 2944: /*
! 2945: * Not handled:
! 2946: *
! 2947: * Transmit buffer unavailable -- normal
! 2948: * condition, nothing to do, really.
! 2949: *
! 2950: * Early receive interrupt -- not available on
! 2951: * all chips, we just use RI. We also only
! 2952: * use single-segment receive DMA, so this
! 2953: * is mostly useless.
! 2954: *
! 2955: * TBD others
! 2956: */
! 2957: }
! 2958:
! 2959: /* Try to get more packets going. */
! 2960: atw_start(ifp);
! 2961:
! 2962: return (handled);
! 2963: }
! 2964:
! 2965: /*
! 2966: * atw_idle:
! 2967: *
! 2968: * Cause the transmit and/or receive processes to go idle.
! 2969: *
! 2970: * XXX It seems that the ADM8211 will not signal the end of the Rx/Tx
! 2971: * process in STSR if I clear SR or ST after the process has already
! 2972: * ceased. Fair enough. But the Rx process status bits in ATW_TEST0
! 2973: * do not seem to be too reliable. Perhaps I have the sense of the
! 2974: * Rx bits switched with the Tx bits?
! 2975: */
! 2976: void
! 2977: atw_idle(struct atw_softc *sc, u_int32_t bits)
! 2978: {
! 2979: u_int32_t ackmask = 0, opmode, stsr, test0;
! 2980: int i, s;
! 2981:
! 2982: s = splnet();
! 2983:
! 2984: opmode = sc->sc_opmode & ~bits;
! 2985:
! 2986: if (bits & ATW_NAR_SR)
! 2987: ackmask |= ATW_INTR_RPS;
! 2988:
! 2989: if (bits & ATW_NAR_ST) {
! 2990: ackmask |= ATW_INTR_TPS;
! 2991: /* set ATW_NAR_HF to flush TX FIFO. */
! 2992: opmode |= ATW_NAR_HF;
! 2993: }
! 2994:
! 2995: ATW_WRITE(sc, ATW_NAR, opmode);
! 2996: DELAY(20 * 1000);
! 2997:
! 2998: for (i = 0; i < 10; i++) {
! 2999: stsr = ATW_READ(sc, ATW_STSR);
! 3000: if ((stsr & ackmask) == ackmask)
! 3001: break;
! 3002: DELAY(1000);
! 3003: }
! 3004:
! 3005: ATW_WRITE(sc, ATW_STSR, stsr & ackmask);
! 3006:
! 3007: if ((stsr & ackmask) == ackmask)
! 3008: goto out;
! 3009:
! 3010: test0 = ATW_READ(sc, ATW_TEST0);
! 3011:
! 3012: if ((bits & ATW_NAR_ST) != 0 && (stsr & ATW_INTR_TPS) == 0 &&
! 3013: (test0 & ATW_TEST0_TS_MASK) != ATW_TEST0_TS_STOPPED) {
! 3014: DPRINTF2(sc, ("%s: transmit process not idle [%s]\n",
! 3015: sc->sc_dev.dv_xname,
! 3016: atw_tx_state[MASK_AND_RSHIFT(test0, ATW_TEST0_TS_MASK)]));
! 3017: DPRINTF2(sc, ("%s: bits %08x test0 %08x stsr %08x\n",
! 3018: sc->sc_dev.dv_xname, bits, test0, stsr));
! 3019: }
! 3020:
! 3021: if ((bits & ATW_NAR_SR) != 0 && (stsr & ATW_INTR_RPS) == 0 &&
! 3022: (test0 & ATW_TEST0_RS_MASK) != ATW_TEST0_RS_STOPPED) {
! 3023: DPRINTF2(sc, ("%s: receive process not idle [%s]\n",
! 3024: sc->sc_dev.dv_xname,
! 3025: atw_rx_state[MASK_AND_RSHIFT(test0, ATW_TEST0_RS_MASK)]));
! 3026: DPRINTF2(sc, ("%s: bits %08x test0 %08x stsr %08x\n",
! 3027: sc->sc_dev.dv_xname, bits, test0, stsr));
! 3028: }
! 3029: out:
! 3030: if ((bits & ATW_NAR_ST) != 0)
! 3031: atw_txdrain(sc);
! 3032: splx(s);
! 3033: return;
! 3034: }
! 3035:
! 3036: /*
! 3037: * atw_linkintr:
! 3038: *
! 3039: * Helper; handle link-status interrupts.
! 3040: */
! 3041: void
! 3042: atw_linkintr(struct atw_softc *sc, u_int32_t linkstatus)
! 3043: {
! 3044: struct ieee80211com *ic = &sc->sc_ic;
! 3045:
! 3046: if (ic->ic_state != IEEE80211_S_RUN)
! 3047: return;
! 3048:
! 3049: if (linkstatus & ATW_INTR_LINKON) {
! 3050: DPRINTF(sc, ("%s: link on\n", sc->sc_dev.dv_xname));
! 3051: sc->sc_rescan_timer = 0;
! 3052: } else if (linkstatus & ATW_INTR_LINKOFF) {
! 3053: DPRINTF(sc, ("%s: link off\n", sc->sc_dev.dv_xname));
! 3054: if (ic->ic_opmode != IEEE80211_M_STA)
! 3055: return;
! 3056: sc->sc_rescan_timer = 3;
! 3057: ic->ic_if.if_timer = 1;
! 3058: }
! 3059: }
! 3060:
! 3061: static __inline int
! 3062: atw_hw_decrypted(struct atw_softc *sc, struct ieee80211_frame *wh)
! 3063: {
! 3064: if ((sc->sc_ic.ic_flags & IEEE80211_F_WEPON) == 0)
! 3065: return 0;
! 3066: if ((wh->i_fc[1] & IEEE80211_FC1_WEP) == 0)
! 3067: return 0;
! 3068: return (sc->sc_wepctl & ATW_WEPCTL_WEPRXBYP) == 0;
! 3069: }
! 3070:
! 3071: /*
! 3072: * atw_rxintr:
! 3073: *
! 3074: * Helper; handle receive interrupts.
! 3075: */
! 3076: void
! 3077: atw_rxintr(struct atw_softc *sc)
! 3078: {
! 3079: static int rate_tbl[] = {2, 4, 11, 22, 44};
! 3080: struct ieee80211com *ic = &sc->sc_ic;
! 3081: struct ieee80211_node *ni;
! 3082: struct ieee80211_frame *wh;
! 3083: struct ifnet *ifp = &ic->ic_if;
! 3084: struct atw_rxsoft *rxs;
! 3085: struct mbuf *m;
! 3086: u_int32_t rxstat;
! 3087: int i, len, rate, rate0;
! 3088: u_int32_t rssi, rssi0;
! 3089:
! 3090: for (i = sc->sc_rxptr;; i = ATW_NEXTRX(i)) {
! 3091: rxs = &sc->sc_rxsoft[i];
! 3092:
! 3093: ATW_CDRXSYNC(sc, i, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
! 3094:
! 3095: rxstat = letoh32(sc->sc_rxdescs[i].ar_stat);
! 3096: rssi0 = letoh32(sc->sc_rxdescs[i].ar_rssi);
! 3097: rate0 = MASK_AND_RSHIFT(rxstat, ATW_RXSTAT_RXDR_MASK);
! 3098:
! 3099: if (rxstat & ATW_RXSTAT_OWN)
! 3100: break; /* We have processed all receive buffers. */
! 3101:
! 3102: DPRINTF3(sc,
! 3103: ("%s: rx stat %08x rssi0 %08x buf1 %08x buf2 %08x\n",
! 3104: sc->sc_dev.dv_xname,
! 3105: rxstat, rssi0,
! 3106: letoh32(sc->sc_rxdescs[i].ar_buf1),
! 3107: letoh32(sc->sc_rxdescs[i].ar_buf2)));
! 3108:
! 3109: /*
! 3110: * Make sure the packet fits in one buffer. This should
! 3111: * always be the case.
! 3112: */
! 3113: if ((rxstat & (ATW_RXSTAT_FS|ATW_RXSTAT_LS)) !=
! 3114: (ATW_RXSTAT_FS|ATW_RXSTAT_LS)) {
! 3115: printf("%s: incoming packet spilled, resetting\n",
! 3116: sc->sc_dev.dv_xname);
! 3117: (void)atw_init(ifp);
! 3118: return;
! 3119: }
! 3120:
! 3121: /*
! 3122: * If an error occurred, update stats, clear the status
! 3123: * word, and leave the packet buffer in place. It will
! 3124: * simply be reused the next time the ring comes around.
! 3125: * If 802.1Q VLAN MTU is enabled, ignore the Frame Too Long
! 3126: * error.
! 3127: */
! 3128:
! 3129: if ((rxstat & ATW_RXSTAT_ES) != 0 &&
! 3130: #if defined(__OpenBSD__)
! 3131: ((sc->sc_ic.ic_if.if_capabilities & IFCAP_VLAN_MTU) == 0 ||
! 3132: #else
! 3133: ((sc->sc_ic.ic_ec.ec_capenable & ETHERCAP_VLAN_MTU) == 0 ||
! 3134: #endif
! 3135: (rxstat & (ATW_RXSTAT_DE | ATW_RXSTAT_SFDE |
! 3136: ATW_RXSTAT_SIGE | ATW_RXSTAT_CRC16E |
! 3137: ATW_RXSTAT_RXTOE | ATW_RXSTAT_CRC32E |
! 3138: ATW_RXSTAT_ICVE)) != 0)) {
! 3139: #define PRINTERR(bit, str) \
! 3140: if (rxstat & (bit)) \
! 3141: printf("%s: receive error: %s\n", \
! 3142: sc->sc_dev.dv_xname, str)
! 3143: ifp->if_ierrors++;
! 3144: PRINTERR(ATW_RXSTAT_DE, "descriptor error");
! 3145: PRINTERR(ATW_RXSTAT_SFDE, "PLCP SFD error");
! 3146: PRINTERR(ATW_RXSTAT_SIGE, "PLCP signal error");
! 3147: PRINTERR(ATW_RXSTAT_CRC16E, "PLCP CRC16 error");
! 3148: PRINTERR(ATW_RXSTAT_RXTOE, "time-out");
! 3149: PRINTERR(ATW_RXSTAT_CRC32E, "FCS error");
! 3150: PRINTERR(ATW_RXSTAT_ICVE, "WEP ICV error");
! 3151: #undef PRINTERR
! 3152: ATW_INIT_RXDESC(sc, i);
! 3153: continue;
! 3154: }
! 3155:
! 3156: bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
! 3157: rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
! 3158:
! 3159: /*
! 3160: * No errors; receive the packet. Note the ADM8211
! 3161: * includes the CRC in promiscuous mode.
! 3162: */
! 3163: len = MASK_AND_RSHIFT(rxstat, ATW_RXSTAT_FL_MASK);
! 3164:
! 3165: /*
! 3166: * Allocate a new mbuf cluster. If that fails, we are
! 3167: * out of memory, and must drop the packet and recycle
! 3168: * the buffer that's already attached to this descriptor.
! 3169: */
! 3170: m = rxs->rxs_mbuf;
! 3171: if (atw_add_rxbuf(sc, i) != 0) {
! 3172: ifp->if_ierrors++;
! 3173: ATW_INIT_RXDESC(sc, i);
! 3174: bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0,
! 3175: rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
! 3176: continue;
! 3177: }
! 3178:
! 3179: ifp->if_ipackets++;
! 3180: if (sc->sc_opmode & ATW_NAR_PR)
! 3181: len -= IEEE80211_CRC_LEN;
! 3182: m->m_pkthdr.rcvif = ifp;
! 3183: m->m_pkthdr.len = m->m_len = MIN(m->m_ext.ext_size, len);
! 3184:
! 3185: if (rate0 >= sizeof(rate_tbl) / sizeof(rate_tbl[0]))
! 3186: rate = 0;
! 3187: else
! 3188: rate = rate_tbl[rate0];
! 3189:
! 3190: /* The RSSI comes straight from a register in the
! 3191: * baseband processor. I know that for the RF3000,
! 3192: * the RSSI register also contains the antenna-selection
! 3193: * bits. Mask those off.
! 3194: *
! 3195: * TBD Treat other basebands.
! 3196: */
! 3197: if (sc->sc_bbptype == ATW_BBPTYPE_RFMD)
! 3198: rssi = rssi0 & RF3000_RSSI_MASK;
! 3199: else
! 3200: rssi = rssi0;
! 3201:
! 3202: #if NBPFILTER > 0
! 3203: /* Pass this up to any BPF listeners. */
! 3204: if (sc->sc_radiobpf != NULL) {
! 3205: struct mbuf mb;
! 3206:
! 3207: struct atw_rx_radiotap_header *tap = &sc->sc_rxtap;
! 3208:
! 3209: tap->ar_rate = rate;
! 3210: tap->ar_chan_freq = ic->ic_bss->ni_chan->ic_freq;
! 3211: tap->ar_chan_flags = ic->ic_bss->ni_chan->ic_flags;
! 3212:
! 3213: /* TBD verify units are dB */
! 3214: tap->ar_antsignal = (int)rssi;
! 3215: /* TBD tap->ar_flags */
! 3216:
! 3217: mb.m_data = (caddr_t)tap;
! 3218: mb.m_len = tap->ar_ihdr.it_len;
! 3219: mb.m_next = m;
! 3220: mb.m_nextpkt = NULL;
! 3221: mb.m_type = 0;
! 3222: mb.m_flags = 0;
! 3223: bpf_mtap(sc->sc_radiobpf, &mb, BPF_DIRECTION_IN);
! 3224: }
! 3225: #endif /* NPBFILTER > 0 */
! 3226:
! 3227: wh = mtod(m, struct ieee80211_frame *);
! 3228: ni = ieee80211_find_rxnode(ic, wh);
! 3229: #if 0
! 3230: if (atw_hw_decrypted(sc, wh))
! 3231: wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
! 3232: #endif
! 3233: ieee80211_input(ifp, m, ni, (int)rssi, 0);
! 3234: /*
! 3235: * The frame may have caused the node to be marked for
! 3236: * reclamation (e.g. in response to a DEAUTH message)
! 3237: * so use release_node here instead of unref_node.
! 3238: */
! 3239: ieee80211_release_node(ic, ni);
! 3240: }
! 3241:
! 3242: /* Update the receive pointer. */
! 3243: sc->sc_rxptr = i;
! 3244: }
! 3245:
! 3246: /*
! 3247: * atw_txintr:
! 3248: *
! 3249: * Helper; handle transmit interrupts.
! 3250: */
! 3251: void
! 3252: atw_txintr(struct atw_softc *sc)
! 3253: {
! 3254: #define TXSTAT_ERRMASK (ATW_TXSTAT_TUF | ATW_TXSTAT_TLT | ATW_TXSTAT_TRT | \
! 3255: ATW_TXSTAT_TRO | ATW_TXSTAT_SOFBR)
! 3256: #define TXSTAT_FMT "\20\31ATW_TXSTAT_SOFBR\32ATW_TXSTAT_TRO\33ATW_TXSTAT_TUF" \
! 3257: "\34ATW_TXSTAT_TRT\35ATW_TXSTAT_TLT"
! 3258: struct ifnet *ifp = &sc->sc_ic.ic_if;
! 3259: struct atw_txsoft *txs;
! 3260: u_int32_t txstat;
! 3261:
! 3262: DPRINTF3(sc, ("%s: atw_txintr: sc_flags 0x%08x\n",
! 3263: sc->sc_dev.dv_xname, sc->sc_flags));
! 3264:
! 3265: ifp->if_flags &= ~IFF_OACTIVE;
! 3266:
! 3267: /*
! 3268: * Go through our Tx list and free mbufs for those
! 3269: * frames that have been transmitted.
! 3270: */
! 3271: while ((txs = SIMPLEQ_FIRST(&sc->sc_txdirtyq)) != NULL) {
! 3272: ATW_CDTXSYNC(sc, txs->txs_lastdesc, 1,
! 3273: BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
! 3274:
! 3275: #ifdef ATW_DEBUG
! 3276: if ((ifp->if_flags & IFF_DEBUG) != 0 && atw_debug > 2) {
! 3277: int i;
! 3278: printf(" txsoft %p transmit chain:\n", txs);
! 3279: ATW_CDTXSYNC(sc, txs->txs_firstdesc,
! 3280: txs->txs_ndescs - 1,
! 3281: BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
! 3282: for (i = txs->txs_firstdesc;; i = ATW_NEXTTX(i)) {
! 3283: printf(" descriptor %d:\n", i);
! 3284: printf(" at_status: 0x%08x\n",
! 3285: letoh32(sc->sc_txdescs[i].at_stat));
! 3286: printf(" at_flags: 0x%08x\n",
! 3287: letoh32(sc->sc_txdescs[i].at_flags));
! 3288: printf(" at_buf1: 0x%08x\n",
! 3289: letoh32(sc->sc_txdescs[i].at_buf1));
! 3290: printf(" at_buf2: 0x%08x\n",
! 3291: letoh32(sc->sc_txdescs[i].at_buf2));
! 3292: if (i == txs->txs_lastdesc)
! 3293: break;
! 3294: }
! 3295: }
! 3296: #endif
! 3297:
! 3298: txstat = letoh32(sc->sc_txdescs[txs->txs_lastdesc].at_stat);
! 3299: if (txstat & ATW_TXSTAT_OWN)
! 3300: break;
! 3301:
! 3302: SIMPLEQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q);
! 3303:
! 3304: sc->sc_txfree += txs->txs_ndescs;
! 3305:
! 3306: bus_dmamap_sync(sc->sc_dmat, txs->txs_dmamap,
! 3307: 0, txs->txs_dmamap->dm_mapsize,
! 3308: BUS_DMASYNC_POSTWRITE);
! 3309: bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap);
! 3310: m_freem(txs->txs_mbuf);
! 3311: txs->txs_mbuf = NULL;
! 3312:
! 3313: SIMPLEQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q);
! 3314:
! 3315: if ((ifp->if_flags & IFF_DEBUG) != 0 &&
! 3316: (txstat & TXSTAT_ERRMASK) != 0) {
! 3317: #if defined(__OpenBSD__)
! 3318: printf("%s: txstat %b %d\n", sc->sc_dev.dv_xname,
! 3319: txstat & TXSTAT_ERRMASK, TXSTAT_FMT,
! 3320: MASK_AND_RSHIFT(txstat, ATW_TXSTAT_ARC_MASK));
! 3321: #else
! 3322: static char txstat_buf[sizeof("ffffffff<>" TXSTAT_FMT)];
! 3323: bitmask_snprintf(txstat & TXSTAT_ERRMASK, TXSTAT_FMT,
! 3324: txstat_buf, sizeof(txstat_buf));
! 3325: printf("%s: txstat %s %d\n", sc->sc_dev.dv_xname,
! 3326: txstat_buf,
! 3327: MASK_AND_RSHIFT(txstat, ATW_TXSTAT_ARC_MASK));
! 3328: #endif
! 3329: }
! 3330:
! 3331: /*
! 3332: * Check for errors and collisions.
! 3333: */
! 3334: if (txstat & ATW_TXSTAT_TUF)
! 3335: sc->sc_stats.ts_tx_tuf++;
! 3336: if (txstat & ATW_TXSTAT_TLT)
! 3337: sc->sc_stats.ts_tx_tlt++;
! 3338: if (txstat & ATW_TXSTAT_TRT)
! 3339: sc->sc_stats.ts_tx_trt++;
! 3340: if (txstat & ATW_TXSTAT_TRO)
! 3341: sc->sc_stats.ts_tx_tro++;
! 3342: if (txstat & ATW_TXSTAT_SOFBR) {
! 3343: sc->sc_stats.ts_tx_sofbr++;
! 3344: }
! 3345:
! 3346: if ((txstat & ATW_TXSTAT_ES) == 0)
! 3347: ifp->if_collisions +=
! 3348: MASK_AND_RSHIFT(txstat, ATW_TXSTAT_ARC_MASK);
! 3349: else
! 3350: ifp->if_oerrors++;
! 3351:
! 3352: ifp->if_opackets++;
! 3353: }
! 3354:
! 3355: /*
! 3356: * If there are no more pending transmissions, cancel the watchdog
! 3357: * timer.
! 3358: */
! 3359: if (txs == NULL)
! 3360: sc->sc_tx_timer = 0;
! 3361: #undef TXSTAT_ERRMASK
! 3362: #undef TXSTAT_FMT
! 3363: }
! 3364:
! 3365: /*
! 3366: * atw_watchdog: [ifnet interface function]
! 3367: *
! 3368: * Watchdog timer handler.
! 3369: */
! 3370: void
! 3371: atw_watchdog(struct ifnet *ifp)
! 3372: {
! 3373: struct atw_softc *sc = ifp->if_softc;
! 3374: struct ieee80211com *ic = &sc->sc_ic;
! 3375: uint32_t test1, rra, rwa;
! 3376:
! 3377: ifp->if_timer = 0;
! 3378: if (ATW_IS_ENABLED(sc) == 0)
! 3379: return;
! 3380:
! 3381: if (sc->sc_rescan_timer) {
! 3382: if (--sc->sc_rescan_timer == 0)
! 3383: (void)ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
! 3384: }
! 3385: if (sc->sc_tx_timer) {
! 3386: if (--sc->sc_tx_timer == 0 &&
! 3387: !SIMPLEQ_EMPTY(&sc->sc_txdirtyq)) {
! 3388: printf("%s: transmit timeout\n", ifp->if_xname);
! 3389: ifp->if_oerrors++;
! 3390: (void)atw_init(ifp);
! 3391: atw_start(ifp);
! 3392: }
! 3393: }
! 3394: if (sc->sc_tx_timer != 0 || sc->sc_rescan_timer != 0)
! 3395: ifp->if_timer = 1;
! 3396:
! 3397: /*
! 3398: * ADM8211B seems to stall every so often, check for this.
! 3399: * These bits are what the Linux driver checks, they don't
! 3400: * seem to be documented by ADMTek/Infineon?
! 3401: */
! 3402: if (sc->sc_rev == ATW_REVISION_BA) {
! 3403: test1 = ATW_READ(sc, ATW_TEST1);
! 3404: rra = (test1 >> 12) & 0x1ff;
! 3405: rwa = (test1 >> 2) & 0x1ff;
! 3406:
! 3407: if ((rra != rwa) && !(test1 & 0x2)) {
! 3408: atw_init(ifp);
! 3409: atw_start(ifp);
! 3410: }
! 3411: }
! 3412:
! 3413: ieee80211_watchdog(ifp);
! 3414: }
! 3415:
! 3416: /*
! 3417: * Arguments in:
! 3418: *
! 3419: * paylen: payload length (no FCS, no WEP header)
! 3420: *
! 3421: * hdrlen: header length
! 3422: *
! 3423: * rate: MSDU speed, units 500kb/s
! 3424: *
! 3425: * flags: IEEE80211_F_SHPREAMBLE (use short preamble),
! 3426: * IEEE80211_F_SHSLOT (use short slot length)
! 3427: *
! 3428: * Arguments out:
! 3429: *
! 3430: * d: 802.11 Duration field for RTS,
! 3431: * 802.11 Duration field for data frame,
! 3432: * PLCP Length for data frame,
! 3433: * residual octets at end of data slot
! 3434: */
! 3435: int
! 3436: atw_compute_duration1(int len, int use_ack, uint32_t flags, int rate,
! 3437: struct atw_duration *d)
! 3438: {
! 3439: int pre, ctsrate;
! 3440: int ack, bitlen, data_dur, remainder;
! 3441:
! 3442: /* RTS reserves medium for SIFS | CTS | SIFS | (DATA) | SIFS | ACK
! 3443: * DATA reserves medium for SIFS | ACK
! 3444: *
! 3445: * XXXMYC: no ACK on multicast/broadcast or control packets
! 3446: */
! 3447:
! 3448: bitlen = len * 8;
! 3449:
! 3450: pre = IEEE80211_DUR_DS_SIFS;
! 3451: if ((flags & IEEE80211_F_SHPREAMBLE) != 0)
! 3452: pre += IEEE80211_DUR_DS_SHORT_PREAMBLE +
! 3453: IEEE80211_DUR_DS_FAST_PLCPHDR;
! 3454: else
! 3455: pre += IEEE80211_DUR_DS_LONG_PREAMBLE +
! 3456: IEEE80211_DUR_DS_SLOW_PLCPHDR;
! 3457:
! 3458: d->d_residue = 0;
! 3459: data_dur = (bitlen * 2) / rate;
! 3460: remainder = (bitlen * 2) % rate;
! 3461: if (remainder != 0) {
! 3462: d->d_residue = (rate - remainder) / 16;
! 3463: data_dur++;
! 3464: }
! 3465:
! 3466: switch (rate) {
! 3467: case 2: /* 1 Mb/s */
! 3468: case 4: /* 2 Mb/s */
! 3469: /* 1 - 2 Mb/s WLAN: send ACK/CTS at 1 Mb/s */
! 3470: ctsrate = 2;
! 3471: break;
! 3472: case 11: /* 5.5 Mb/s */
! 3473: case 22: /* 11 Mb/s */
! 3474: case 44: /* 22 Mb/s */
! 3475: /* 5.5 - 11 Mb/s WLAN: send ACK/CTS at 2 Mb/s */
! 3476: ctsrate = 4;
! 3477: break;
! 3478: default:
! 3479: /* TBD */
! 3480: return -1;
! 3481: }
! 3482:
! 3483: d->d_plcp_len = data_dur;
! 3484:
! 3485: ack = (use_ack) ? pre + (IEEE80211_DUR_DS_SLOW_ACK * 2) / ctsrate : 0;
! 3486:
! 3487: d->d_rts_dur =
! 3488: pre + (IEEE80211_DUR_DS_SLOW_CTS * 2) / ctsrate +
! 3489: pre + data_dur +
! 3490: ack;
! 3491:
! 3492: d->d_data_dur = ack;
! 3493:
! 3494: return 0;
! 3495: }
! 3496:
! 3497: /*
! 3498: * Arguments in:
! 3499: *
! 3500: * wh: 802.11 header
! 3501: *
! 3502: * len: packet length
! 3503: *
! 3504: * rate: MSDU speed, units 500kb/s
! 3505: *
! 3506: * fraglen: fragment length, set to maximum (or higher) for no
! 3507: * fragmentation
! 3508: *
! 3509: * flags: IEEE80211_F_WEPON (hardware adds WEP),
! 3510: * IEEE80211_F_SHPREAMBLE (use short preamble),
! 3511: * IEEE80211_F_SHSLOT (use short slot length)
! 3512: *
! 3513: * Arguments out:
! 3514: *
! 3515: * d0: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields
! 3516: * of first/only fragment
! 3517: *
! 3518: * dn: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields
! 3519: * of first/only fragment
! 3520: */
! 3521: int
! 3522: atw_compute_duration(struct ieee80211_frame *wh, int len, uint32_t flags,
! 3523: int fraglen, int rate, struct atw_duration *d0, struct atw_duration *dn,
! 3524: int *npktp, int debug)
! 3525: {
! 3526: int ack, rc;
! 3527: int firstlen, hdrlen, lastlen, lastlen0, npkt, overlen, paylen;
! 3528:
! 3529: if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
! 3530: hdrlen = sizeof(struct ieee80211_frame_addr4);
! 3531: else
! 3532: hdrlen = sizeof(struct ieee80211_frame);
! 3533:
! 3534: paylen = len - hdrlen;
! 3535:
! 3536: if ((flags & IEEE80211_F_WEPON) != 0)
! 3537: overlen = IEEE80211_WEP_TOTLEN + IEEE80211_CRC_LEN;
! 3538: else
! 3539: overlen = IEEE80211_CRC_LEN;
! 3540:
! 3541: npkt = paylen / fraglen;
! 3542: lastlen0 = paylen % fraglen;
! 3543:
! 3544: if (npkt == 0) /* no fragments */
! 3545: lastlen = paylen + overlen;
! 3546: else if (lastlen0 != 0) { /* a short "tail" fragment */
! 3547: lastlen = lastlen0 + overlen;
! 3548: npkt++;
! 3549: } else /* full-length "tail" fragment */
! 3550: lastlen = fraglen + overlen;
! 3551:
! 3552: if (npktp != NULL)
! 3553: *npktp = npkt;
! 3554:
! 3555: if (npkt > 1)
! 3556: firstlen = fraglen + overlen;
! 3557: else
! 3558: firstlen = paylen + overlen;
! 3559:
! 3560: if (debug) {
! 3561: printf("%s: npkt %d firstlen %d lastlen0 %d lastlen %d "
! 3562: "fraglen %d overlen %d len %d rate %d flags %08x\n",
! 3563: __func__, npkt, firstlen, lastlen0, lastlen, fraglen,
! 3564: overlen, len, rate, flags);
! 3565: }
! 3566:
! 3567: ack = !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
! 3568: (wh->i_fc[1] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL;
! 3569:
! 3570: rc = atw_compute_duration1(firstlen + hdrlen, ack, flags, rate, d0);
! 3571: if (rc == -1)
! 3572: return rc;
! 3573:
! 3574: if (npkt <= 1) {
! 3575: *dn = *d0;
! 3576: return 0;
! 3577: }
! 3578: return atw_compute_duration1(lastlen + hdrlen, ack, flags, rate, dn);
! 3579: }
! 3580:
! 3581: #ifdef ATW_DEBUG
! 3582: void
! 3583: atw_dump_pkt(struct ifnet *ifp, struct mbuf *m0)
! 3584: {
! 3585: struct atw_softc *sc = ifp->if_softc;
! 3586: struct mbuf *m;
! 3587: int i, noctets = 0;
! 3588:
! 3589: printf("%s: %d-byte packet\n", sc->sc_dev.dv_xname,
! 3590: m0->m_pkthdr.len);
! 3591:
! 3592: for (m = m0; m; m = m->m_next) {
! 3593: if (m->m_len == 0)
! 3594: continue;
! 3595: for (i = 0; i < m->m_len; i++) {
! 3596: printf(" %02x", ((u_int8_t*)m->m_data)[i]);
! 3597: if (++noctets % 24 == 0)
! 3598: printf("\n");
! 3599: }
! 3600: }
! 3601: printf("%s%s: %d bytes emitted\n",
! 3602: (noctets % 24 != 0) ? "\n" : "", sc->sc_dev.dv_xname, noctets);
! 3603: }
! 3604: #endif /* ATW_DEBUG */
! 3605:
! 3606: /*
! 3607: * atw_start: [ifnet interface function]
! 3608: *
! 3609: * Start packet transmission on the interface.
! 3610: */
! 3611: void
! 3612: atw_start(struct ifnet *ifp)
! 3613: {
! 3614: struct atw_softc *sc = ifp->if_softc;
! 3615: struct ieee80211com *ic = &sc->sc_ic;
! 3616: struct ieee80211_node *ni;
! 3617: struct ieee80211_frame *wh;
! 3618: struct atw_frame *hh;
! 3619: struct mbuf *m0, *m;
! 3620: struct atw_txsoft *txs, *last_txs;
! 3621: struct atw_txdesc *txd;
! 3622: int do_encrypt, npkt, rate;
! 3623: bus_dmamap_t dmamap;
! 3624: int ctl, error, firsttx, nexttx, lasttx = -1, first, ofree, seg;
! 3625:
! 3626: DPRINTF2(sc, ("%s: atw_start: sc_flags 0x%08x, if_flags 0x%08x\n",
! 3627: sc->sc_dev.dv_xname, sc->sc_flags, ifp->if_flags));
! 3628:
! 3629: if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
! 3630: return;
! 3631:
! 3632: /*
! 3633: * Remember the previous number of free descriptors and
! 3634: * the first descriptor we'll use.
! 3635: */
! 3636: ofree = sc->sc_txfree;
! 3637: firsttx = sc->sc_txnext;
! 3638:
! 3639: DPRINTF2(sc, ("%s: atw_start: txfree %d, txnext %d\n",
! 3640: sc->sc_dev.dv_xname, ofree, firsttx));
! 3641:
! 3642: /*
! 3643: * Loop through the send queue, setting up transmit descriptors
! 3644: * until we drain the queue, or use up all available transmit
! 3645: * descriptors.
! 3646: */
! 3647: while ((txs = SIMPLEQ_FIRST(&sc->sc_txfreeq)) != NULL &&
! 3648: sc->sc_txfree != 0) {
! 3649:
! 3650: /*
! 3651: * Grab a packet off the management queue, if it
! 3652: * is not empty. Otherwise, from the data queue.
! 3653: */
! 3654: IF_DEQUEUE(&ic->ic_mgtq, m0);
! 3655: if (m0 != NULL) {
! 3656: ni = (struct ieee80211_node *)m0->m_pkthdr.rcvif;
! 3657: m0->m_pkthdr.rcvif = NULL;
! 3658: } else {
! 3659: /* send no data packets until we are associated */
! 3660: if (ic->ic_state != IEEE80211_S_RUN)
! 3661: break;
! 3662: IFQ_DEQUEUE(&ifp->if_snd, m0);
! 3663: if (m0 == NULL)
! 3664: break;
! 3665: #if NBPFILTER > 0
! 3666: if (ifp->if_bpf != NULL)
! 3667: bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
! 3668: #endif /* NBPFILTER > 0 */
! 3669: if ((m0 = ieee80211_encap(ifp, m0, &ni)) == NULL) {
! 3670: ifp->if_oerrors++;
! 3671: break;
! 3672: }
! 3673:
! 3674: if (sc->sc_ic.ic_flags & IEEE80211_F_WEPON) {
! 3675: if ((m0 = ieee80211_wep_crypt(ifp, m0, 1)) == NULL) {
! 3676: ifp->if_oerrors++;
! 3677: break;
! 3678: }
! 3679: }
! 3680: }
! 3681:
! 3682: wh = mtod(m0, struct ieee80211_frame *);
! 3683:
! 3684: /* XXX do real rate control */
! 3685: if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
! 3686: IEEE80211_FC0_TYPE_MGT)
! 3687: rate = 2;
! 3688: else
! 3689: rate = MAX(2, ieee80211_get_rate(ic));
! 3690:
! 3691: if (atw_compute_duration(wh, m0->m_pkthdr.len,
! 3692: ic->ic_flags & ~IEEE80211_F_WEPON, ic->ic_fragthreshold,
! 3693: rate, &txs->txs_d0, &txs->txs_dn, &npkt,
! 3694: (sc->sc_if.if_flags & (IFF_DEBUG|IFF_LINK2)) ==
! 3695: (IFF_DEBUG|IFF_LINK2)) == -1) {
! 3696: DPRINTF2(sc, ("%s: fail compute duration\n", __func__));
! 3697: m_freem(m0);
! 3698: break;
! 3699: }
! 3700:
! 3701: /*
! 3702: * XXX Misleading if fragmentation is enabled. Better
! 3703: * to fragment in software?
! 3704: */
! 3705: *(uint16_t *)wh->i_dur = htole16(txs->txs_d0.d_rts_dur);
! 3706:
! 3707: #if NBPFILTER > 0
! 3708: /*
! 3709: * Pass the packet to any BPF listeners.
! 3710: */
! 3711: if (ic->ic_rawbpf != NULL)
! 3712: bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT);
! 3713:
! 3714: if (sc->sc_radiobpf != NULL) {
! 3715: struct mbuf mb;
! 3716: struct atw_tx_radiotap_header *tap = &sc->sc_txtap;
! 3717:
! 3718: tap->at_rate = rate;
! 3719: tap->at_chan_freq = ic->ic_bss->ni_chan->ic_freq;
! 3720: tap->at_chan_flags = ic->ic_bss->ni_chan->ic_flags;
! 3721:
! 3722: /* TBD tap->at_flags */
! 3723:
! 3724: mb.m_data = (caddr_t)tap;
! 3725: mb.m_len = tap->at_ihdr.it_len;
! 3726: mb.m_next = m0;
! 3727: mb.m_nextpkt = NULL;
! 3728: mb.m_type = 0;
! 3729: mb.m_flags = 0;
! 3730: bpf_mtap(sc->sc_radiobpf, &mb, BPF_DIRECTION_OUT);
! 3731: }
! 3732: #endif /* NBPFILTER > 0 */
! 3733:
! 3734: M_PREPEND(m0, offsetof(struct atw_frame, atw_ihdr), M_DONTWAIT);
! 3735:
! 3736: if (ni != NULL)
! 3737: ieee80211_release_node(ic, ni);
! 3738:
! 3739: if (m0 == NULL) {
! 3740: ifp->if_oerrors++;
! 3741: break;
! 3742: }
! 3743:
! 3744: /* just to make sure. */
! 3745: m0 = m_pullup(m0, sizeof(struct atw_frame));
! 3746:
! 3747: if (m0 == NULL) {
! 3748: ifp->if_oerrors++;
! 3749: break;
! 3750: }
! 3751:
! 3752: hh = mtod(m0, struct atw_frame *);
! 3753: wh = &hh->atw_ihdr;
! 3754:
! 3755: do_encrypt = ((wh->i_fc[1] & IEEE80211_FC1_WEP) != 0) ? 1 : 0;
! 3756:
! 3757: /* Copy everything we need from the 802.11 header:
! 3758: * Frame Control; address 1, address 3, or addresses
! 3759: * 3 and 4. NIC fills in BSSID, SA.
! 3760: */
! 3761: if (wh->i_fc[1] & IEEE80211_FC1_DIR_TODS) {
! 3762: if (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS)
! 3763: panic("%s: illegal WDS frame",
! 3764: sc->sc_dev.dv_xname);
! 3765: memcpy(hh->atw_dst, wh->i_addr3, IEEE80211_ADDR_LEN);
! 3766: } else
! 3767: memcpy(hh->atw_dst, wh->i_addr1, IEEE80211_ADDR_LEN);
! 3768:
! 3769: *(u_int16_t*)hh->atw_fc = *(u_int16_t*)wh->i_fc;
! 3770:
! 3771: /* initialize remaining Tx parameters */
! 3772: memset(&hh->u, 0, sizeof(hh->u));
! 3773:
! 3774: hh->atw_rate = rate * 5;
! 3775: /* XXX this could be incorrect if M_FCS. _encap should
! 3776: * probably strip FCS just in case it sticks around in
! 3777: * bridged packets.
! 3778: */
! 3779: hh->atw_service = IEEE80211_PLCP_SERVICE; /* XXX guess */
! 3780: hh->atw_paylen = htole16(m0->m_pkthdr.len -
! 3781: sizeof(struct atw_frame));
! 3782:
! 3783: hh->atw_fragthr = htole16(ATW_FRAGTHR_FRAGTHR_MASK);
! 3784: hh->atw_rtylmt = 3;
! 3785: hh->atw_hdrctl = htole16(ATW_HDRCTL_UNKNOWN1);
! 3786: #if 0
! 3787: if (do_encrypt) {
! 3788: hh->atw_hdrctl |= htole16(ATW_HDRCTL_WEP);
! 3789: hh->atw_keyid = ic->ic_wep_txkey;
! 3790: }
! 3791: #endif
! 3792:
! 3793: hh->atw_head_plcplen = htole16(txs->txs_d0.d_plcp_len);
! 3794: hh->atw_tail_plcplen = htole16(txs->txs_dn.d_plcp_len);
! 3795: if (txs->txs_d0.d_residue)
! 3796: hh->atw_head_plcplen |= htole16(0x8000);
! 3797: if (txs->txs_dn.d_residue)
! 3798: hh->atw_tail_plcplen |= htole16(0x8000);
! 3799: hh->atw_head_dur = htole16(txs->txs_d0.d_rts_dur);
! 3800: hh->atw_tail_dur = htole16(txs->txs_dn.d_rts_dur);
! 3801:
! 3802: /* never fragment multicast frames */
! 3803: if (IEEE80211_IS_MULTICAST(hh->atw_dst)) {
! 3804: hh->atw_fragthr = htole16(ATW_FRAGTHR_FRAGTHR_MASK);
! 3805: } else if (sc->sc_flags & ATWF_RTSCTS) {
! 3806: hh->atw_hdrctl |= htole16(ATW_HDRCTL_RTSCTS);
! 3807: }
! 3808:
! 3809: #ifdef ATW_DEBUG
! 3810: hh->atw_fragnum = 0;
! 3811:
! 3812: if ((ifp->if_flags & IFF_DEBUG) != 0 && atw_debug > 2) {
! 3813: printf("%s: dst = %s, rate = 0x%02x, "
! 3814: "service = 0x%02x, paylen = 0x%04x\n",
! 3815: sc->sc_dev.dv_xname, ether_sprintf(hh->atw_dst),
! 3816: hh->atw_rate, hh->atw_service, hh->atw_paylen);
! 3817:
! 3818: printf("%s: fc[0] = 0x%02x, fc[1] = 0x%02x, "
! 3819: "dur1 = 0x%04x, dur2 = 0x%04x, "
! 3820: "dur3 = 0x%04x, rts_dur = 0x%04x\n",
! 3821: sc->sc_dev.dv_xname, hh->atw_fc[0], hh->atw_fc[1],
! 3822: hh->atw_tail_plcplen, hh->atw_head_plcplen,
! 3823: hh->atw_tail_dur, hh->atw_head_dur);
! 3824:
! 3825: printf("%s: hdrctl = 0x%04x, fragthr = 0x%04x, "
! 3826: "fragnum = 0x%02x, rtylmt = 0x%04x\n",
! 3827: sc->sc_dev.dv_xname, hh->atw_hdrctl,
! 3828: hh->atw_fragthr, hh->atw_fragnum, hh->atw_rtylmt);
! 3829:
! 3830: printf("%s: keyid = %d\n",
! 3831: sc->sc_dev.dv_xname, hh->atw_keyid);
! 3832:
! 3833: atw_dump_pkt(ifp, m0);
! 3834: }
! 3835: #endif /* ATW_DEBUG */
! 3836:
! 3837: dmamap = txs->txs_dmamap;
! 3838:
! 3839: /*
! 3840: * Load the DMA map. Copy and try (once) again if the packet
! 3841: * didn't fit in the alloted number of segments.
! 3842: */
! 3843: for (first = 1;
! 3844: (error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0,
! 3845: BUS_DMA_WRITE|BUS_DMA_NOWAIT)) != 0 && first;
! 3846: first = 0) {
! 3847: MGETHDR(m, M_DONTWAIT, MT_DATA);
! 3848: if (m == NULL) {
! 3849: printf("%s: unable to allocate Tx mbuf\n",
! 3850: sc->sc_dev.dv_xname);
! 3851: break;
! 3852: }
! 3853: if (m0->m_pkthdr.len > MHLEN) {
! 3854: MCLGET(m, M_DONTWAIT);
! 3855: if ((m->m_flags & M_EXT) == 0) {
! 3856: printf("%s: unable to allocate Tx "
! 3857: "cluster\n", sc->sc_dev.dv_xname);
! 3858: m_freem(m);
! 3859: break;
! 3860: }
! 3861: }
! 3862: m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, caddr_t));
! 3863: m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len;
! 3864: m_freem(m0);
! 3865: m0 = m;
! 3866: m = NULL;
! 3867: }
! 3868: if (error != 0) {
! 3869: printf("%s: unable to load Tx buffer, "
! 3870: "error = %d\n", sc->sc_dev.dv_xname, error);
! 3871: m_freem(m0);
! 3872: break;
! 3873: }
! 3874:
! 3875: /*
! 3876: * Ensure we have enough descriptors free to describe
! 3877: * the packet.
! 3878: */
! 3879: if (dmamap->dm_nsegs > sc->sc_txfree) {
! 3880: /*
! 3881: * Not enough free descriptors to transmit
! 3882: * this packet. Unload the DMA map and
! 3883: * drop the packet. Notify the upper layer
! 3884: * that there are no more slots left.
! 3885: *
! 3886: * XXX We could allocate an mbuf and copy, but
! 3887: * XXX it is worth it?
! 3888: */
! 3889: ifp->if_flags |= IFF_OACTIVE;
! 3890: bus_dmamap_unload(sc->sc_dmat, dmamap);
! 3891: m_freem(m0);
! 3892: break;
! 3893: }
! 3894:
! 3895: /*
! 3896: * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET.
! 3897: */
! 3898:
! 3899: /* Sync the DMA map. */
! 3900: bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize,
! 3901: BUS_DMASYNC_PREWRITE);
! 3902:
! 3903: /* XXX arbitrary retry limit; 8 because I have seen it in
! 3904: * use already and maybe 0 means "no tries" !
! 3905: */
! 3906: ctl = htole32(LSHIFT(8, ATW_TXCTL_TL_MASK));
! 3907:
! 3908: DPRINTF2(sc, ("%s: TXDR <- max(10, %d)\n",
! 3909: sc->sc_dev.dv_xname, rate * 5));
! 3910: ctl |= htole32(LSHIFT(MAX(10, rate * 5), ATW_TXCTL_TXDR_MASK));
! 3911:
! 3912: /*
! 3913: * Initialize the transmit descriptors.
! 3914: */
! 3915: for (nexttx = sc->sc_txnext, seg = 0;
! 3916: seg < dmamap->dm_nsegs;
! 3917: seg++, nexttx = ATW_NEXTTX(nexttx)) {
! 3918: /*
! 3919: * If this is the first descriptor we're
! 3920: * enqueueing, don't set the OWN bit just
! 3921: * yet. That could cause a race condition.
! 3922: * We'll do it below.
! 3923: */
! 3924: txd = &sc->sc_txdescs[nexttx];
! 3925: txd->at_ctl = ctl |
! 3926: ((nexttx == firsttx) ? 0 : htole32(ATW_TXCTL_OWN));
! 3927:
! 3928: txd->at_buf1 = htole32(dmamap->dm_segs[seg].ds_addr);
! 3929: txd->at_flags =
! 3930: htole32(LSHIFT(dmamap->dm_segs[seg].ds_len,
! 3931: ATW_TXFLAG_TBS1_MASK)) |
! 3932: ((nexttx == (ATW_NTXDESC - 1))
! 3933: ? htole32(ATW_TXFLAG_TER) : 0);
! 3934: lasttx = nexttx;
! 3935: }
! 3936:
! 3937: if (lasttx == -1)
! 3938: panic("%s: bad lastx", ifp->if_xname);
! 3939: /* Set `first segment' and `last segment' appropriately. */
! 3940: sc->sc_txdescs[sc->sc_txnext].at_flags |=
! 3941: htole32(ATW_TXFLAG_FS);
! 3942: sc->sc_txdescs[lasttx].at_flags |= htole32(ATW_TXFLAG_LS);
! 3943:
! 3944: #ifdef ATW_DEBUG
! 3945: if ((ifp->if_flags & IFF_DEBUG) != 0 && atw_debug > 2) {
! 3946: printf(" txsoft %p transmit chain:\n", txs);
! 3947: for (seg = sc->sc_txnext;; seg = ATW_NEXTTX(seg)) {
! 3948: printf(" descriptor %d:\n", seg);
! 3949: printf(" at_ctl: 0x%08x\n",
! 3950: letoh32(sc->sc_txdescs[seg].at_ctl));
! 3951: printf(" at_flags: 0x%08x\n",
! 3952: letoh32(sc->sc_txdescs[seg].at_flags));
! 3953: printf(" at_buf1: 0x%08x\n",
! 3954: letoh32(sc->sc_txdescs[seg].at_buf1));
! 3955: printf(" at_buf2: 0x%08x\n",
! 3956: letoh32(sc->sc_txdescs[seg].at_buf2));
! 3957: if (seg == lasttx)
! 3958: break;
! 3959: }
! 3960: }
! 3961: #endif
! 3962:
! 3963: /* Sync the descriptors we're using. */
! 3964: ATW_CDTXSYNC(sc, sc->sc_txnext, dmamap->dm_nsegs,
! 3965: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
! 3966:
! 3967: /*
! 3968: * Store a pointer to the packet so we can free it later,
! 3969: * and remember what txdirty will be once the packet is
! 3970: * done.
! 3971: */
! 3972: txs->txs_mbuf = m0;
! 3973: txs->txs_firstdesc = sc->sc_txnext;
! 3974: txs->txs_lastdesc = lasttx;
! 3975: txs->txs_ndescs = dmamap->dm_nsegs;
! 3976:
! 3977: /* Advance the tx pointer. */
! 3978: sc->sc_txfree -= dmamap->dm_nsegs;
! 3979: sc->sc_txnext = nexttx;
! 3980:
! 3981: SIMPLEQ_REMOVE_HEAD(&sc->sc_txfreeq, txs_q);
! 3982: SIMPLEQ_INSERT_TAIL(&sc->sc_txdirtyq, txs, txs_q);
! 3983:
! 3984: last_txs = txs;
! 3985: }
! 3986:
! 3987: if (txs == NULL || sc->sc_txfree == 0) {
! 3988: /* No more slots left; notify upper layer. */
! 3989: ifp->if_flags |= IFF_OACTIVE;
! 3990: }
! 3991:
! 3992: if (sc->sc_txfree != ofree) {
! 3993: DPRINTF2(sc, ("%s: packets enqueued, IC on %d, OWN on %d\n",
! 3994: sc->sc_dev.dv_xname, lasttx, firsttx));
! 3995: /*
! 3996: * Cause a transmit interrupt to happen on the
! 3997: * last packet we enqueued.
! 3998: */
! 3999: sc->sc_txdescs[lasttx].at_flags |= htole32(ATW_TXFLAG_IC);
! 4000: ATW_CDTXSYNC(sc, lasttx, 1,
! 4001: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
! 4002:
! 4003: /*
! 4004: * The entire packet chain is set up. Give the
! 4005: * first descriptor to the chip now.
! 4006: */
! 4007: sc->sc_txdescs[firsttx].at_ctl |= htole32(ATW_TXCTL_OWN);
! 4008: ATW_CDTXSYNC(sc, firsttx, 1,
! 4009: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
! 4010:
! 4011: /* Wake up the transmitter. */
! 4012: ATW_WRITE(sc, ATW_TDR, 0x1);
! 4013:
! 4014: /* Set a watchdog timer in case the chip flakes out. */
! 4015: sc->sc_tx_timer = 5;
! 4016: ifp->if_timer = 1;
! 4017: }
! 4018: }
! 4019:
! 4020: /*
! 4021: * atw_power:
! 4022: *
! 4023: * Power management (suspend/resume) hook.
! 4024: */
! 4025: void
! 4026: atw_power(int why, void *arg)
! 4027: {
! 4028: struct atw_softc *sc = arg;
! 4029: struct ifnet *ifp = &sc->sc_ic.ic_if;
! 4030: int s;
! 4031:
! 4032: DPRINTF(sc, ("%s: atw_power(%d,)\n", sc->sc_dev.dv_xname, why));
! 4033:
! 4034: s = splnet();
! 4035: switch (why) {
! 4036: case PWR_STANDBY:
! 4037: /* XXX do nothing. */
! 4038: break;
! 4039: case PWR_SUSPEND:
! 4040: atw_stop(ifp, 1);
! 4041: if (sc->sc_power != NULL)
! 4042: (*sc->sc_power)(sc, why);
! 4043: break;
! 4044: case PWR_RESUME:
! 4045: if (ifp->if_flags & IFF_UP) {
! 4046: if (sc->sc_power != NULL)
! 4047: (*sc->sc_power)(sc, why);
! 4048: atw_init(ifp);
! 4049: }
! 4050: break;
! 4051: #if !defined(__OpenBSD__)
! 4052: case PWR_SOFTSUSPEND:
! 4053: case PWR_SOFTSTANDBY:
! 4054: case PWR_SOFTRESUME:
! 4055: break;
! 4056: #endif
! 4057: }
! 4058: splx(s);
! 4059: }
! 4060:
! 4061: /*
! 4062: * atw_ioctl: [ifnet interface function]
! 4063: *
! 4064: * Handle control requests from the operator.
! 4065: */
! 4066: int
! 4067: atw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
! 4068: {
! 4069: struct atw_softc *sc = ifp->if_softc;
! 4070: struct ieee80211com *ic = &sc->sc_ic;
! 4071: struct ifreq *ifr = (struct ifreq *)data;
! 4072: struct ifaddr *ifa = (struct ifaddr *)data;
! 4073: int s, error = 0;
! 4074:
! 4075: /* XXX monkey see, monkey do. comes from wi_ioctl. */
! 4076: if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
! 4077: return ENXIO;
! 4078:
! 4079: s = splnet();
! 4080:
! 4081: switch (cmd) {
! 4082: case SIOCSIFMTU:
! 4083: if (ifr->ifr_mtu > ETHERMTU || ifr->ifr_mtu < ETHERMIN) {
! 4084: error = EINVAL;
! 4085: } else if (ifp->if_mtu != ifr->ifr_mtu) {
! 4086: ifp->if_mtu = ifr->ifr_mtu;
! 4087: }
! 4088: break;
! 4089: case SIOCSIFADDR:
! 4090: ifp->if_flags |= IFF_UP;
! 4091: #ifdef INET
! 4092: if (ifa->ifa_addr->sa_family == AF_INET) {
! 4093: arp_ifinit(&ic->ic_ac, ifa);
! 4094: }
! 4095: #endif /* INET */
! 4096: /* FALLTHROUGH */
! 4097: case SIOCSIFFLAGS:
! 4098: if (ifp->if_flags & IFF_UP) {
! 4099: if (ATW_IS_ENABLED(sc)) {
! 4100: /*
! 4101: * To avoid rescanning another access point,
! 4102: * do not call atw_init() here. Instead,
! 4103: * only reflect media settings.
! 4104: */
! 4105: atw_filter_setup(sc);
! 4106: } else
! 4107: error = atw_init(ifp);
! 4108: } else if (ATW_IS_ENABLED(sc))
! 4109: atw_stop(ifp, 1);
! 4110: break;
! 4111: case SIOCADDMULTI:
! 4112: case SIOCDELMULTI:
! 4113: error = (cmd == SIOCADDMULTI) ?
! 4114: #if defined(__OpenBSD__)
! 4115: ether_addmulti(ifr, &sc->sc_ic.ic_ac) :
! 4116: ether_delmulti(ifr, &sc->sc_ic.ic_ac);
! 4117: #else
! 4118: ether_addmulti(ifr, &sc->sc_ic.ic_ec) :
! 4119: ether_delmulti(ifr, &sc->sc_ic.ic_ec);
! 4120: #endif
! 4121:
! 4122: if (error == ENETRESET) {
! 4123: if (ifp->if_flags & IFF_RUNNING)
! 4124: atw_filter_setup(sc); /* do not rescan */
! 4125: error = 0;
! 4126: }
! 4127: break;
! 4128: default:
! 4129: error = ieee80211_ioctl(ifp, cmd, data);
! 4130: if (error == ENETRESET) {
! 4131: if (ATW_IS_ENABLED(sc))
! 4132: error = atw_init(ifp);
! 4133: else
! 4134: error = 0;
! 4135: }
! 4136: break;
! 4137: }
! 4138:
! 4139: /* Try to get more packets going. */
! 4140: if (ATW_IS_ENABLED(sc))
! 4141: atw_start(ifp);
! 4142:
! 4143: splx(s);
! 4144: return (error);
! 4145: }
! 4146:
! 4147: int
! 4148: atw_media_change(struct ifnet *ifp)
! 4149: {
! 4150: int error;
! 4151:
! 4152: error = ieee80211_media_change(ifp);
! 4153: if (error == ENETRESET) {
! 4154: if ((ifp->if_flags & (IFF_RUNNING|IFF_UP)) ==
! 4155: (IFF_RUNNING|IFF_UP))
! 4156: atw_init(ifp); /* XXX lose error */
! 4157: error = 0;
! 4158: }
! 4159: return error;
! 4160: }
! 4161:
! 4162: void
! 4163: atw_media_status(struct ifnet *ifp, struct ifmediareq *imr)
! 4164: {
! 4165: struct atw_softc *sc = ifp->if_softc;
! 4166:
! 4167: if (ATW_IS_ENABLED(sc) == 0) {
! 4168: imr->ifm_active = IFM_IEEE80211 | IFM_NONE;
! 4169: imr->ifm_status = 0;
! 4170: return;
! 4171: }
! 4172: ieee80211_media_status(ifp, imr);
! 4173: }
CVSweb