diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2005-09-24 09:22:27 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2005-09-24 09:22:27 +0000 |
commit | b50cd3c29b30dfb1ff1611edd279aa3162eaf8f6 (patch) | |
tree | f9cfc8e7cc56e57ac4675c1a306a16a04b02cc16 /sys/dev/ic/atw.c | |
parent | a0878f42ce5ffa6f16de0605549063c35234ce80 (diff) |
Make use of ieee80211_ibss_merge() from net80211.
Based on changes made by David Young to NetBSD.
Diffstat (limited to 'sys/dev/ic/atw.c')
-rw-r--r-- | sys/dev/ic/atw.c | 195 |
1 files changed, 42 insertions, 153 deletions
diff --git a/sys/dev/ic/atw.c b/sys/dev/ic/atw.c index 9d52832459f..efae7ce4e96 100644 --- a/sys/dev/ic/atw.c +++ b/sys/dev/ic/atw.c @@ -1,4 +1,4 @@ -/* $OpenBSD: atw.c,v 1.38 2005/09/23 23:01:21 jsg Exp $ */ +/* $OpenBSD: atw.c,v 1.39 2005/09/24 09:22:26 jsg Exp $ */ /* $NetBSD: atw.c,v 1.69 2004/07/23 07:07:55 dyoung Exp $ */ /*- @@ -240,7 +240,7 @@ void atw_write_sram(struct atw_softc *, u_int, u_int8_t *, u_int); int atw_read_srom(struct atw_softc *); /* BSS setup */ -void atw_tsf(struct atw_softc *); +void atw_predict_beacon(struct atw_softc *sc); void atw_start_beacon(struct atw_softc *, int); void atw_write_bssid(struct atw_softc *); void atw_write_ssid(struct atw_softc *); @@ -257,10 +257,9 @@ void atw_filter_setup(struct atw_softc *); void atw_frame_setdurs(struct atw_softc *, struct atw_frame *, int, int); struct ieee80211_node *atw_node_alloc(struct ieee80211com *); void atw_node_free(struct ieee80211com *, struct ieee80211_node *); -void atw_recv_beacon(struct ieee80211com *, struct mbuf *, - struct ieee80211_node *, int, int, u_int32_t); static __inline uint32_t atw_last_even_tsft(uint32_t, uint32_t, uint32_t); -static __inline void atw_tsft(struct atw_softc *, uint32_t *, uint32_t *); +uint64_t atw_get_tsft(struct atw_softc *sc); +void atw_change_ibss(struct atw_softc *); /* * Tuner/transceiver/modem @@ -2263,7 +2262,13 @@ atw_write_wep(struct atw_softc *sc) sizeof(buf)); } -const struct timeval atw_beacon_mininterval = {.tv_sec = 1, .tv_usec = 0}; +void +atw_change_ibss(struct atw_softc *sc) +{ + atw_predict_beacon(sc); + atw_write_bssid(sc); + atw_start_beacon(sc, 1); +} void atw_recv_mgmt(struct ieee80211com *ic, struct mbuf *m, @@ -2271,148 +2276,28 @@ atw_recv_mgmt(struct ieee80211com *ic, struct mbuf *m, { struct atw_softc *sc = (struct atw_softc*)ic->ic_softc; + /* The ADM8211A answers probe requests. */ + if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_REQ && + sc->sc_rev < ATW_REVISION_BA) + return; + + (*sc->sc_recv_mgmt)(ic, m, ni, subtype, rssi, rstamp); + switch (subtype) { - case IEEE80211_FC0_SUBTYPE_PROBE_REQ: - /* do nothing: hardware answers probe request */ - break; case IEEE80211_FC0_SUBTYPE_PROBE_RESP: case IEEE80211_FC0_SUBTYPE_BEACON: - atw_recv_beacon(ic, m, ni, subtype, rssi, rstamp); + if (ic->ic_opmode != IEEE80211_M_IBSS || + ic->ic_state != IEEE80211_S_RUN) + break; + if (ieee80211_ibss_merge(ic, ni, atw_get_tsft(sc)) == ENETRESET) + atw_change_ibss(sc); break; default: - (*sc->sc_recv_mgmt)(ic, m, ni, subtype, rssi, rstamp); break; } return; } -static int -do_slow_print(struct atw_softc *sc, int *did_print) -{ - if ((sc->sc_if.if_flags & IFF_LINK0) == 0) - return 0; - if (!*did_print && (sc->sc_if.if_flags & IFF_DEBUG) == 0 && - !ratecheck(&sc->sc_last_beacon, &atw_beacon_mininterval)) - return 0; - - *did_print = 1; - return 1; -} - -/* In ad hoc mode, atw_recv_beacon is responsible for the coalescence - * of IBSSs with like SSID/channel but different BSSID. It joins the - * oldest IBSS (i.e., with greatest TSF time), since that is the WECA - * convention. Possibly the ADMtek chip does this for us; I will have - * to test to find out. - * - * XXX we should add the duration field of the received beacon to - * the TSF time it contains before comparing it with the ADM8211's - * TSF. - */ -void -atw_recv_beacon(struct ieee80211com *ic, struct mbuf *m0, - struct ieee80211_node *ni, int subtype, int rssi, u_int32_t rstamp) -{ - struct atw_softc *sc = (struct atw_softc*)ic->ic_softc; - struct ieee80211_frame *wh; - uint32_t tsftl, tsfth; - uint32_t bcn_tsftl, bcn_tsfth; - int did_print = 0, sign; - union { - uint32_t words[2]; - uint8_t tstamp[8]; - } u; - - (*sc->sc_recv_mgmt)(ic, m0, ni, subtype, rssi, rstamp); - - if (ic->ic_state != IEEE80211_S_RUN) - return; - - atw_tsft(sc, &tsfth, &tsftl); - - (void)memcpy(&u, &ni->ni_tstamp[0], sizeof(u)); - bcn_tsftl = letoh32(u.words[0]); - bcn_tsfth = letoh32(u.words[1]); - - /* we are faster, let the other guy catch up */ - if (bcn_tsfth < tsfth) - sign = -1; - else if (bcn_tsfth == tsfth && bcn_tsftl < tsftl) - sign = -1; - else - sign = 1; - - if (memcmp(ni->ni_bssid, ic->ic_bss->ni_bssid, - IEEE80211_ADDR_LEN) == 0) { - if (!do_slow_print(sc, &did_print)) - return; - printf("%s: tsft offset %s%ull\n", sc->sc_dev.dv_xname, - (sign < 0) ? "-" : "", - (sign < 0) - ? ((((uint64_t)tsfth << 32) | tsftl) - - (((uint64_t)bcn_tsfth << 32) | bcn_tsftl)) - : ((((uint64_t)bcn_tsfth << 32) | bcn_tsftl) - - (((uint64_t)tsfth << 32) | tsftl))); - return; - } - - if (sign < 0) - return; - - if (ieee80211_match_bss(ic, ni) != 0) - return; - - if (do_slow_print(sc, &did_print)) { - printf("%s: atw_recv_beacon: bssid mismatch %s\n", - sc->sc_dev.dv_xname, ether_sprintf(ni->ni_bssid)); - } - - if (ic->ic_opmode != IEEE80211_M_IBSS) - return; - - if (do_slow_print(sc, &did_print)) { - printf("%s: my tsft %llx beacon tsft %llx\n", - sc->sc_dev.dv_xname, ((uint64_t)tsfth << 32) | tsftl, - ((uint64_t)bcn_tsfth << 32) | bcn_tsftl); - } - - wh = mtod(m0, struct ieee80211_frame *); - - if (do_slow_print(sc, &did_print)) { - printf("%s: sync TSF with %s\n", - sc->sc_dev.dv_xname, ether_sprintf(wh->i_addr2)); - } - - ic->ic_flags &= ~IEEE80211_F_SIBSS; - - (void)memcpy(&ic->ic_bss->ni_tstamp[0], &u, sizeof(u)); - - atw_tsf(sc); - - /* negotiate rates with new IBSS */ - ieee80211_fix_rate(ic, ni, IEEE80211_F_DOFRATE | - IEEE80211_F_DONEGO | IEEE80211_F_DODEL); - if (ni->ni_rates.rs_nrates == 0) { - if (do_slow_print(sc, &did_print)) { - printf("%s: rates mismatch, BSSID %s\n", - sc->sc_dev.dv_xname, ether_sprintf(ni->ni_bssid)); - } - return; - } - - if (do_slow_print(sc, &did_print)) { - printf("%s: sync BSSID %s -> ", - sc->sc_dev.dv_xname, ether_sprintf(ic->ic_bss->ni_bssid)); - printf("%s ", ether_sprintf(ni->ni_bssid)); - printf("(from %s)\n", ether_sprintf(wh->i_addr2)); - } - - (*ic->ic_node_copy)(ic, ic->ic_bss, ni); - - atw_write_bssid(sc); - atw_start_beacon(sc, 1); -} - /* Write the SSID in the ieee80211com to the SRAM on the ADM8211. * In ad hoc mode, the SSID is written to the beacons sent by the * ADM8211. In both ad hoc and infrastructure mode, beacons received @@ -2555,16 +2440,18 @@ atw_last_even_tsft(uint32_t tsfth, uint32_t tsftl, uint32_t ival) return ((0xFFFFFFFF % ival + 1) * tsfth + tsftl) % ival; } -static __inline void -atw_tsft(struct atw_softc *sc, uint32_t *tsfth, uint32_t *tsftl) +uint64_t +atw_get_tsft(struct atw_softc *sc) { int i; + uint32_t tsfth, tsftl; for (i = 0; i < 2; i++) { - *tsfth = ATW_READ(sc, ATW_TSFTH); - *tsftl = ATW_READ(sc, ATW_TSFTL); - if (ATW_READ(sc, ATW_TSFTH) == *tsfth) + tsfth = ATW_READ(sc, ATW_TSFTH); + tsftl = ATW_READ(sc, ATW_TSFTL); + if (ATW_READ(sc, ATW_TSFTH) == tsfth) break; } + return ((uint64_t)tsfth << 32) | tsftl; } /* If we've created an IBSS, write the TSF time in the ADM8211 to @@ -2574,33 +2461,35 @@ atw_tsft(struct atw_softc *sc, uint32_t *tsfth, uint32_t *tsftl) * write it to the ADM8211. */ void -atw_tsf(struct atw_softc *sc) +atw_predict_beacon(struct atw_softc *sc) { #define TBTTOFS 20 /* TU */ struct ieee80211com *ic = &sc->sc_ic; + uint64_t tsft; uint32_t ival, past_even, tbtt, tsfth, tsftl; union { - uint32_t words[2]; + uint64_t word; uint8_t tstamp[8]; } u; if ((ic->ic_opmode == IEEE80211_M_HOSTAP) || ((ic->ic_opmode == IEEE80211_M_IBSS) && (ic->ic_flags & IEEE80211_F_SIBSS))) { - atw_tsft(sc, &tsfth, &tsftl); - u.words[0] = htole32(tsftl); - u.words[1] = htole32(tsfth); - (void)memcpy(&ic->ic_bss->ni_tstamp[0], &u, + tsft = atw_get_tsft(sc); + u.word = htole64(tsft); + (void)memcpy(&ic->ic_bss->ni_tstamp[0], &u.tstamp[0], sizeof(ic->ic_bss->ni_tstamp)); } else { (void)memcpy(&u, &ic->ic_bss->ni_tstamp[0], sizeof(u)); - tsftl = letoh32(u.words[0]); - tsfth = letoh32(u.words[1]); + tsft = letoh64(u.word); } ival = ic->ic_bss->ni_intval * IEEE80211_DUR_TU; + tsftl = tsft & 0xFFFFFFFF; + tsfth = tsft >> 32; + /* We sent/received the last beacon `past' microseconds * after the interval divided the TSF timer. */ @@ -2615,7 +2504,7 @@ atw_tsf(struct atw_softc *sc) LSHIFT(1, ATW_TOFS1_TSFTOFSR_MASK) | LSHIFT(TBTTOFS, ATW_TOFS1_TBTTOFS_MASK) | LSHIFT(MASK_AND_RSHIFT(tbtt - TBTTOFS * IEEE80211_DUR_TU, - ATW_TBTTPRE_MASK), ATW_TOFS1_TBTTPRE_MASK)); + ATW_TBTTPRE_MASK), ATW_TOFS1_TBTTPRE_MASK)); #undef TBTTOFS } @@ -2686,7 +2575,7 @@ atw_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) DPRINTF(sc, ("%s: reg[ATW_BPLI] = %08x\n", sc->sc_dev.dv_xname, ATW_READ(sc, ATW_BPLI))); - atw_tsf(sc); + atw_predict_beacon(sc); break; } |