summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2005-09-24 09:22:27 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2005-09-24 09:22:27 +0000
commitb50cd3c29b30dfb1ff1611edd279aa3162eaf8f6 (patch)
treef9cfc8e7cc56e57ac4675c1a306a16a04b02cc16 /sys/dev/ic
parenta0878f42ce5ffa6f16de0605549063c35234ce80 (diff)
Make use of ieee80211_ibss_merge() from net80211.
Based on changes made by David Young to NetBSD.
Diffstat (limited to 'sys/dev/ic')
-rw-r--r--sys/dev/ic/atw.c195
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;
}