diff options
author | Damien Bergamini <damien@cvs.openbsd.org> | 2007-11-19 21:26:20 +0000 |
---|---|---|
committer | Damien Bergamini <damien@cvs.openbsd.org> | 2007-11-19 21:26:20 +0000 |
commit | 37707f83eead960d523e63f93f587fbf95219a23 (patch) | |
tree | 5cc1a39c70442e2b8f7e71d696231682bb4cd272 | |
parent | 691603a120624405a190658d46a8dde1ea0dd8b7 (diff) |
802.11 radiotap + various tweaks
-rw-r--r-- | sys/dev/ic/rt2860.c | 202 | ||||
-rw-r--r-- | sys/dev/ic/rt2860reg.h | 17 | ||||
-rw-r--r-- | sys/dev/ic/rt2860var.h | 53 |
3 files changed, 205 insertions, 67 deletions
diff --git a/sys/dev/ic/rt2860.c b/sys/dev/ic/rt2860.c index 4775a2f35f1..24e8496b0c3 100644 --- a/sys/dev/ic/rt2860.c +++ b/sys/dev/ic/rt2860.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rt2860.c,v 1.5 2007/11/17 15:39:38 damien Exp $ */ +/* $OpenBSD: rt2860.c,v 1.6 2007/11/19 21:26:19 damien Exp $ */ /*- * Copyright (c) 2007 @@ -106,7 +106,7 @@ void rt2860_tx_intr(struct rt2860_softc *, int); void rt2860_rx_intr(struct rt2860_softc *); int rt2860_ack_rate(struct ieee80211com *, int); uint16_t rt2860_txtime(int, int, uint32_t); -uint8_t rt2860_rate2mcs(struct rt2860_softc *, uint8_t); +uint8_t rt2860_rate2mcs(uint8_t); int rt2860_tx_data(struct rt2860_softc *, struct mbuf *, struct ieee80211_node *, int); void rt2860_start(struct ifnet *); @@ -290,6 +290,19 @@ rt2860_attach(void *xsc, int id) ic->ic_newstate = rt2860_newstate; ieee80211_media_init(ifp, rt2860_media_change, ieee80211_media_status); +#if NBPFILTER > 0 + bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO, + sizeof (struct ieee80211_frame) + 64); + + sc->sc_rxtap_len = sizeof sc->sc_rxtapu; + sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len); + sc->sc_rxtap.wr_ihdr.it_present = htole32(RT2860_RX_RADIOTAP_PRESENT); + + sc->sc_txtap_len = sizeof sc->sc_txtapu; + sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len); + sc->sc_txtap.wt_ihdr.it_present = htole32(RT2860_TX_RADIOTAP_PRESENT); +#endif + return 0; fail2: rt2860_free_rx_ring(sc, &sc->rxq); @@ -716,15 +729,17 @@ void rt2860_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew) { struct rt2860_softc *sc = ic->ic_softc; - uint8_t wcid; + uint8_t wcid = 0; int i; - wcid = RT2860_AID2WCID(ni->ni_associd); - - /* init WCID table entry */ - RAL_WRITE_REGION_1(sc, RT2860_WCID_ENTRY(wcid), - ni->ni_macaddr, IEEE80211_ADDR_LEN); + if (isnew && ni->ni_associd != 0) { + /* only interested in true associations */ + wcid = RT2860_AID2WCID(ni->ni_associd); + /* init WCID table entry */ + RAL_WRITE_REGION_1(sc, RT2860_WCID_ENTRY(wcid), + ni->ni_macaddr, IEEE80211_ADDR_LEN); + } ieee80211_amrr_node_init(&sc->amrr, &sc->amn[wcid]); /* set rate to some reasonable initial value */ @@ -733,8 +748,8 @@ rt2860_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew) i--); ni->ni_txrate = i; - DPRINTF(("new assoc addr=%s WCID=%d, initial rate=%d\n", - ether_sprintf(ni->ni_macaddr), wcid, + DPRINTF(("new assoc isnew=%d addr=%s WCID=%d, initial rate=%d\n", + isnew, ether_sprintf(ni->ni_macaddr), wcid, ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL)); } @@ -948,8 +963,13 @@ rt2860_rx_intr(struct rt2860_softc *sc) struct ieee80211_node *ni; struct mbuf *m, *mnew; u_int hdrlen; - uint8_t rssi; + uint8_t ant, rssi; int error; +#if NBPFILTER > 0 + struct rt2860_rx_radiotap_header *tap = &sc->sc_rxtap; + struct mbuf mb; + uint16_t phy; +#endif for (;;) { struct rt2860_rx_data *data = &sc->rxq.data[sc->rxq.cur]; @@ -1035,11 +1055,58 @@ rt2860_rx_intr(struct rt2860_softc *sc) wh = mtod(m, struct ieee80211_frame *); } + ant = rt2860_maxrssi_chain(sc, rxwi); + rssi = rxwi->rssi[ant]; + +#if NBPFILTER > 0 + if (sc->sc_drvbpf == NULL) + goto skipbpf; + + tap->wr_flags = 0; + tap->wr_chan_freq = htole16(ic->ic_ibss_chan->ic_freq); + tap->wr_chan_flags = htole16(ic->ic_ibss_chan->ic_flags); + tap->wr_antsignal = rssi; + tap->wr_antenna = ant; + tap->wr_dbm_antsignal = rt2860_rssi2dbm(sc, rssi, ant); + tap->wr_rate = 2; /* in case it can't be found below */ + phy = letoh16(rxwi->phy); + switch (phy & RT2860_PHY_MODE) { + case RT2860_PHY_CCK: + switch ((phy & RT2860_PHY_MCS) & ~RT2860_PHY_SHPRE) { + case 0: tap->wr_rate = 2; break; + case 1: tap->wr_rate = 4; break; + case 2: tap->wr_rate = 11; break; + case 3: tap->wr_rate = 22; break; + } + if (phy & RT2860_PHY_SHPRE) + tap->wr_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; + break; + case RT2860_PHY_OFDM: + switch (phy & RT2860_PHY_MCS) { + case 0: tap->wr_rate = 12; break; + case 1: tap->wr_rate = 18; break; + case 2: tap->wr_rate = 24; break; + case 3: tap->wr_rate = 36; break; + case 4: tap->wr_rate = 48; break; + case 5: tap->wr_rate = 72; break; + case 6: tap->wr_rate = 96; break; + case 7: tap->wr_rate = 108; break; + } + break; + } + mb.m_data = (caddr_t)tap; + mb.m_len = sc->sc_rxtap_len; + mb.m_next = m; + mb.m_nextpkt = NULL; + mb.m_type = 0; + mb.m_flags = 0; + bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN); +skipbpf: +#endif /* grab a reference to the source node */ ni = ieee80211_find_rxnode(ic, wh); /* send the frame to the 802.11 layer */ - rssi = rxwi->rssi[rt2860_maxrssi_chain(sc, rxwi)]; ieee80211_input(ifp, m, ni, rssi, 0); /* node is no longer needed */ @@ -1186,37 +1253,23 @@ rt2860_txtime(int len, int rate, uint32_t flags) } uint8_t -rt2860_rate2mcs(struct rt2860_softc *sc, uint8_t rate) +rt2860_rate2mcs(uint8_t rate) { - struct ieee80211com *ic = &sc->sc_ic; - - if (!RAL_RATE_IS_OFDM(rate)) { - if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) { - switch (rate) { - case 2: return 0; - case 4: return 9; - case 11: return 10; - case 22: return 11; - } - } else { - switch (rate) { - case 2: return 0; - case 4: return 1; - case 11: return 2; - case 22: return 3; - } - } - } else { - switch (rate) { - case 12: return 0; - case 18: return 1; - case 24: return 2; - case 36: return 3; - case 48: return 4; - case 72: return 5; - case 96: return 6; - case 108: return 7; - } + switch (rate) { + /* CCK rates */ + case 2: return 0; + case 4: return 1; + case 11: return 2; + case 22: return 3; + /* OFDM rates */ + case 12: return 0; + case 18: return 1; + case 24: return 2; + case 36: return 3; + case 48: return 4; + case 72: return 5; + case 96: return 6; + case 108: return 7; } return 0; /* shouldn't get there */ } @@ -1257,7 +1310,7 @@ rt2860_tx_data(struct rt2860_softc *sc, struct mbuf *m0, rate &= IEEE80211_RATE_VAL; /* get MCS code from rate */ - mcs = rt2860_rate2mcs(sc, rate); + mcs = rt2860_rate2mcs(rate); if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { m0 = ieee80211_wep_crypt(ifp, m0, 1); @@ -1274,10 +1327,15 @@ rt2860_tx_data(struct rt2860_softc *sc, struct mbuf *m0, txwi->wcid = (type == IEEE80211_FC0_TYPE_DATA) ? RT2860_AID2WCID(ni->ni_associd) : 0xff; txwi->len = htole16(m0->m_pkthdr.len); + if (!RAL_RATE_IS_OFDM(rate)) { + txwi->phy = htole16(RT2860_PHY_CCK); + if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) + mcs |= RT2860_PHY_SHPRE; + } else + txwi->phy = htole16(RT2860_PHY_OFDM); + txwi->phy |= htole16(mcs); + /* store MCS into driver-private field for rate control */ txwi->len |= htole16(mcs << RT2860_TX_PID_SHIFT); - txwi->phy = htole16(mcs); - if (RAL_RATE_IS_OFDM(rate)) - txwi->phy |= htole16(RT2860_TX_OFDM); /* check if RTS/CTS or CTS-to-self protection is required */ if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && @@ -1301,6 +1359,29 @@ rt2860_tx_data(struct rt2860_softc *sc, struct mbuf *m0, /* NOTE: beacons do not pass through tx_data() */ txwi->flags |= RT2860_TX_TS; +#if NBPFILTER > 0 + if (sc->sc_drvbpf != NULL) { + struct rt2860_tx_radiotap_header *tap = &sc->sc_txtap; + struct mbuf mb; + + tap->wt_flags = 0; + tap->wt_rate = rate; + tap->wt_chan_freq = htole16(ic->ic_ibss_chan->ic_freq); + tap->wt_chan_flags = htole16(ic->ic_ibss_chan->ic_flags); + tap->wt_hwqueue = qid; + if (mcs & RT2860_PHY_SHPRE) + tap->wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; + + mb.m_data = (caddr_t)tap; + mb.m_len = sc->sc_txtap_len; + mb.m_next = m0; + mb.m_nextpkt = NULL; + mb.m_type = 0; + mb.m_flags = 0; + bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT); + } +#endif + /* copy and trim 802.11 header */ memcpy(&txwi->wh, wh, hdrlen); m_adj(m0, hdrlen); @@ -1949,7 +2030,7 @@ rt2860_set_key(struct ieee80211com *ic, struct ieee80211_node *ni, uint32_t attr; uint8_t mode, wcid; - /* map net80211 ciphers to RT2860 security mode */ + /* map net80211 cipher to RT2860 security mode */ switch (k->k_cipher) { case IEEE80211_CIPHER_WEP40: mode = RT2860_MODE_WEP40; @@ -1975,9 +2056,9 @@ rt2860_set_key(struct ieee80211com *ic, struct ieee80211_node *ni, RAL_WRITE_REGION_1(sc, base + 24, k->k_rxmic, 8); attr = RAL_READ(sc, RT2860_SKEY_MODE_0_7); + attr &= ~(0xf << (k->k_id * 4)); attr |= mode << (k->k_id * 4); RAL_WRITE(sc, RT2860_SKEY_MODE_0_7, attr); - } else { /* install pairwise key */ wcid = RT2860_AID2WCID(ni->ni_associd); @@ -2019,7 +2100,7 @@ int8_t rt2860_rssi2dbm(struct rt2860_softc *sc, uint8_t rssi, uint8_t rxchain) { struct ieee80211com *ic = &sc->sc_ic; - struct ieee80211_channel *c = ic->ic_bss->ni_chan; + struct ieee80211_channel *c = ic->ic_ibss_chan; int delta; if (IEEE80211_IS_CHAN_5GHZ(c)) { @@ -2541,13 +2622,15 @@ rt2860_init(struct ifnet *ifp) RAL_WRITE(sc, RT2860_WPDMA_GLO_CFG, tmp); /* set Rx filter */ - tmp = - RT2860_DROP_CRC_ERR | RT2860_DROP_PHY_ERR | RT2860_DROP_UC_NOME | - RT2860_DROP_VER_ERR | RT2860_DROP_DUPL | RT2860_DROP_CFACK | - RT2860_DROP_CFEND | RT2860_DROP_ACK | RT2860_DROP_CTS | - RT2860_DROP_BA | RT2860_DROP_CTRL_RSV; - if (ic->ic_opmode == IEEE80211_M_STA) - tmp |= RT2860_DROP_RTS | RT2860_DROP_PSPOLL; + tmp = RT2860_DROP_CRC_ERR | RT2860_DROP_PHY_ERR; + if (ic->ic_opmode != IEEE80211_M_MONITOR) { + tmp |= RT2860_DROP_UC_NOME | RT2860_DROP_DUPL | + RT2860_DROP_CTS | RT2860_DROP_BA | RT2860_DROP_ACK | + RT2860_DROP_VER_ERR | RT2860_DROP_CTRL_RSV | + RT2860_DROP_CFACK | RT2860_DROP_CFEND; + if (ic->ic_opmode == IEEE80211_M_STA) + tmp |= RT2860_DROP_RTS | RT2860_DROP_PSPOLL; + } RAL_WRITE(sc, RT2860_RX_FILTR_CFG, tmp); RAL_WRITE(sc, RT2860_MAC_SYS_CTRL, @@ -2595,7 +2678,7 @@ rt2860_stop(struct ifnet *ifp, int disable) /* clear shared key table */ RAL_SET_REGION_4(sc, RT2860_SKEY(0, 0), 0, 8 * 32); /* clear shared key mode */ - RAL_SET_REGION_4(sc, 0x7000, 0, 4); + RAL_SET_REGION_4(sc, RT2860_SKEY_MODE_0_7, 0, 4); /* disable interrupts */ RAL_WRITE(sc, RT2860_INT_MASK, 0); @@ -2725,7 +2808,9 @@ rt2860_setup_beacon(struct rt2860_softc *sc) txwi.len = htole16(m->m_pkthdr.len); /* send beacons at the lowest available rate */ rate = (ic->ic_curmode == IEEE80211_MODE_11A) ? 12 : 2; - txwi.phy = htole16(rt2860_rate2mcs(sc, rate)); + txwi.phy = htole16(rt2860_rate2mcs(rate)); + if (rate == 12) + txwi.phy |= htole16(RT2860_PHY_OFDM); txwi.txop = RT2860_TX_TXOP_HT; txwi.flags = RT2860_TX_TS; @@ -2780,4 +2865,3 @@ rt2860_shutdown(void *arg) rt2860_stop(ifp, 1); } - diff --git a/sys/dev/ic/rt2860reg.h b/sys/dev/ic/rt2860reg.h index 66b89929ef8..d8060053c7f 100644 --- a/sys/dev/ic/rt2860reg.h +++ b/sys/dev/ic/rt2860reg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rt2860reg.h,v 1.2 2007/11/17 15:39:38 damien Exp $ */ +/* $OpenBSD: rt2860reg.h,v 1.3 2007/11/19 21:26:19 damien Exp $ */ /*- * Copyright (c) 2007 @@ -651,12 +651,15 @@ struct rt2860_txwi { #define RT2860_TX_TXOP_BACKOFF 3 uint16_t phy; -#define RT2860_TX_CCK (0 << 14) -#define RT2860_TX_OFDM (1 << 14) -#define RT2860_TX_HT (2 << 14) -#define RT2860_TX_HT_GF (3 << 14) -#define RT2860_TX_SGI (1 << 8) -#define RT2860_TX_BW (1 << 7) +#define RT2860_PHY_MODE 0xc000 +#define RT2860_PHY_CCK (0 << 14) +#define RT2860_PHY_OFDM (1 << 14) +#define RT2860_PHY_HT (2 << 14) +#define RT2860_PHY_HT_GF (3 << 14) +#define RT2860_PHY_SGI (1 << 8) +#define RT2860_PHY_BW40 (1 << 7) +#define RT2860_PHY_MCS 0x7f +#define RT2860_PHY_SHPRE (1 << 3) uint8_t xflags; #define RT2860_TX_BAWINSIZE_SHIFT 2 diff --git a/sys/dev/ic/rt2860var.h b/sys/dev/ic/rt2860var.h index 4371928a2f3..3e7b91fc049 100644 --- a/sys/dev/ic/rt2860var.h +++ b/sys/dev/ic/rt2860var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rt2860var.h,v 1.2 2007/11/17 15:39:38 damien Exp $ */ +/* $OpenBSD: rt2860var.h,v 1.3 2007/11/19 21:26:19 damien Exp $ */ /*- * Copyright (c) 2007 @@ -27,6 +27,40 @@ #define RT2860_WCID_MAX 254 #define RT2860_AID2WCID(aid) ((aid) & 0xff) +struct rt2860_rx_radiotap_header { + struct ieee80211_radiotap_header wr_ihdr; + uint8_t wr_flags; + uint8_t wr_rate; + uint16_t wr_chan_freq; + uint16_t wr_chan_flags; + uint8_t wr_dbm_antsignal; + uint8_t wr_antenna; + uint8_t wr_antsignal; +} __packed; + +#define RT2860_RX_RADIOTAP_PRESENT \ + (1 << IEEE80211_RADIOTAP_FLAGS | \ + 1 << IEEE80211_RADIOTAP_RATE | \ + 1 << IEEE80211_RADIOTAP_CHANNEL | \ + 1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL | \ + 1 << IEEE80211_RADIOTAP_ANTENNA | \ + 1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) + +struct rt2860_tx_radiotap_header { + struct ieee80211_radiotap_header wt_ihdr; + uint8_t wt_flags; + uint8_t wt_rate; + uint16_t wt_chan_freq; + uint16_t wt_chan_flags; + uint8_t wt_hwqueue; +} __packed; + +#define RT2860_TX_RADIOTAP_PRESENT \ + (1 << IEEE80211_RADIOTAP_FLAGS | \ + 1 << IEEE80211_RADIOTAP_RATE | \ + 1 << IEEE80211_RADIOTAP_CHANNEL | \ + 1 << IEEE80211_RADIOTAP_HWQUEUE) + struct rt2860_tx_data { struct rt2860_txwi *txwi; struct mbuf *m; @@ -122,6 +156,23 @@ struct rt2860_softc { uint32_t txpow40mhz_5ghz[5]; struct ieee80211_amrr_node amn[RT2860_WCID_MAX + 1]; + +#if NBPFILTER > 0 + caddr_t sc_drvbpf; + union { + struct rt2860_rx_radiotap_header th; + uint8_t pad[64]; + } sc_rxtapu; +#define sc_rxtap sc_rxtapu.th + int sc_rxtap_len; + + union { + struct rt2860_tx_radiotap_header th; + uint8_t pad[64]; + } sc_txtapu; +#define sc_txtap sc_txtapu.th + int sc_txtap_len; +#endif }; int rt2860_attach(void *, int); |