Index: if_athioctl.h =================================================================== --- if_athioctl.h (revision 237108) +++ if_athioctl.h (working copy) @@ -195,10 +195,71 @@ (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \ (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | \ (1 << IEEE80211_RADIOTAP_XCHANNEL) | \ + (1 << IEEE80211_RADIOTAP_VENDOREXT) | \ + (1 << IEEE80211_RADIOTAP_EXT) | \ 0) +/* + * This is higher than the vendor bitmap used inside + * the Atheros reference codebase. + */ + +/* Bit 8 */ +#define ATH_RADIOTAP_VENDOR_HEADER 8 + + +/* + * Using four chains makes all the fields in the + * per-chain info header be 4-byte aligned. + */ +#define ATH_RADIOTAP_MAX_CHAINS 4 + +/* + * The vendor radiotap header data needs to be: + * + * + Aligned to a 4 byte address + * + .. so all internal fields are 4 bytes aligned; + * + .. and no 64 bit fields are allowed. + * + * So padding is required to ensure this is the case. + * + * Note that because of the lack of alignment with the + * vendor header (6 bytes), the first field must be + * two bytes so it can be accessed by alignment-strict + * platform (eg MIPS.) + */ +struct ath_radiotap_vendor_hdr { /* 30 bytes */ + uint8_t vh_version; /* 1 */ + uint8_t vh_rx_chainmask; /* 1 */ + + /* At this point it should be 4 byte aligned */ + uint32_t evm[ATH_RADIOTAP_MAX_CHAINS]; /* 4 * 4 = 16 */ + + uint8_t rssi_ctl[ATH_RADIOTAP_MAX_CHAINS]; /* 4 */ + uint8_t rssi_ext[ATH_RADIOTAP_MAX_CHAINS]; /* 4 */ + + uint8_t vh_phyerr_code; /* Phy error code, or 0xff */ + uint8_t vh_rs_status; /* RX status */ + uint8_t vh_rssi; /* Raw RSSI */ + uint8_t vh_pad1[1]; /* Pad to 4 byte boundary */ +} __packed; + struct ath_rx_radiotap_header { struct ieee80211_radiotap_header wr_ihdr; + + /* Vendor extension header bitmap */ + uint32_t wr_ext_bitmap; /* 4 */ + + /* + * This padding is needed because: + * + the radiotap header is 8 bytes; + * + the extension bitmap is 4 bytes; + * + the tsf is 8 bytes, so it must start on an 8 byte + * boundary. + */ + uint32_t wr_pad1; + + /* Normal radiotap fields */ u_int64_t wr_tsf; u_int8_t wr_flags; u_int8_t wr_rate; @@ -210,6 +271,24 @@ u_int16_t wr_chan_freq; u_int8_t wr_chan_ieee; int8_t wr_chan_maxpow; + + /* + * Vendor header section, as required by the + * presence of the vendor extension bit and bitmap + * entry. + * + * XXX This must be aligned to a 4 byte address? + * XXX or 8 byte address? + */ + struct ieee80211_radiotap_vendor_header wr_vh; /* 6 bytes */ + + /* + * Because of the lack of alignment enforced by the above + * header, this vendor section won't be aligned in any + * useful way. So, this will include a two-byte version + * value which will force the structure to be 4-byte aligned. + */ + struct ath_radiotap_vendor_hdr wr_v; } __packed; #define ATH_TX_RADIOTAP_PRESENT ( \ Index: if_ath_rx.c =================================================================== --- if_ath_rx.c (revision 237174) +++ if_ath_rx.c (working copy) @@ -355,6 +355,54 @@ } static void +ath_rx_tap_vendor(struct ifnet *ifp, struct mbuf *m, + const struct ath_rx_status *rs, u_int64_t tsf, int16_t nf) +{ + struct ath_softc *sc = ifp->if_softc; + + /* Fill in the extension bitmap */ + sc->sc_rx_th.wr_ext_bitmap = htole32(1 << ATH_RADIOTAP_VENDOR_HEADER); + + /* Fill in the vendor header */ + sc->sc_rx_th.wr_vh.vh_oui[0] = 0x7f; + sc->sc_rx_th.wr_vh.vh_oui[1] = 0x03; + sc->sc_rx_th.wr_vh.vh_oui[2] = 0x00; + + /* XXX what should this be? */ + sc->sc_rx_th.wr_vh.vh_sub_ns = 0; + sc->sc_rx_th.wr_vh.vh_skip_len = + htole16(sizeof(struct ath_radiotap_vendor_hdr)); + + /* General version info */ + sc->sc_rx_th.wr_v.vh_version = 1; + + sc->sc_rx_th.wr_v.vh_rx_chainmask = sc->sc_rxchainmask; + + /* rssi */ + sc->sc_rx_th.wr_v.rssi_ctl[0] = rs->rs_rssi_ctl[0]; + sc->sc_rx_th.wr_v.rssi_ctl[1] = rs->rs_rssi_ctl[1]; + sc->sc_rx_th.wr_v.rssi_ctl[2] = rs->rs_rssi_ctl[2]; + sc->sc_rx_th.wr_v.rssi_ext[0] = rs->rs_rssi_ext[0]; + sc->sc_rx_th.wr_v.rssi_ext[1] = rs->rs_rssi_ext[1]; + sc->sc_rx_th.wr_v.rssi_ext[2] = rs->rs_rssi_ext[2]; + + /* evm */ + sc->sc_rx_th.wr_v.evm[0] = rs->rs_evm0; + sc->sc_rx_th.wr_v.evm[1] = rs->rs_evm1; + sc->sc_rx_th.wr_v.evm[2] = rs->rs_evm2; + /* XXX TODO: extend this to include 3-stream EVM */ + + /* phyerr info */ + if (rs->rs_status & HAL_RXERR_PHY) + sc->sc_rx_th.wr_v.vh_phyerr_code = rs->rs_phyerr; + else + sc->sc_rx_th.wr_v.vh_phyerr_code = 0xff; + sc->sc_rx_th.wr_v.vh_rs_status = rs->rs_status; + sc->sc_rx_th.wr_v.vh_rssi = rs->rs_rssi; +} + + +static void ath_rx_tap(struct ifnet *ifp, struct mbuf *m, const struct ath_rx_status *rs, u_int64_t tsf, int16_t nf) { @@ -552,6 +600,7 @@ m->m_pkthdr.len = m->m_len = len; bf->bf_m = NULL; ath_rx_tap(ifp, m, rs, rstamp, nf); + ath_rx_tap_vendor(ifp, m, rs, rstamp, nf); ieee80211_radiotap_rx_all(ic, m); m_freem(m); } @@ -646,8 +695,10 @@ * material required by ieee80211_input. Note that * noise setting is filled in above. */ - if (ieee80211_radiotap_active(ic)) + if (ieee80211_radiotap_active(ic)) { ath_rx_tap(ifp, m, rs, rstamp, nf); + ath_rx_tap_vendor(ifp, m, rs, rstamp, nf); + } /* * From this point on we assume the frame is at least Index: ath_dfs/null/dfs_null.c =================================================================== --- ath_dfs/null/dfs_null.c (revision 237108) +++ ath_dfs/null/dfs_null.c (working copy) @@ -120,7 +120,7 @@ int ath_dfs_radar_enable(struct ath_softc *sc, struct ieee80211_channel *chan) { -#if 0 +#if 1 HAL_PHYERR_PARAM pe; /* Check if the current channel is radar-enabled */ Index: if_ath.c =================================================================== --- if_ath.c (revision 237179) +++ if_ath.c (working copy) @@ -799,10 +799,14 @@ ic->ic_update_chw = ath_update_chw; #endif /* ATH_ENABLE_11N */ - ieee80211_radiotap_attach(ic, - &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th), + /* + * There's one vendor bitmap entry in the RX radiotap + * header; make sure that's taken into account. + */ + ieee80211_radiotap_attachv(ic, + &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th), 0, ATH_TX_RADIOTAP_PRESENT, - &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th), + &sc->sc_rx_th.wr_ihdr, sizeof(sc->sc_rx_th), 1, ATH_RX_RADIOTAP_PRESENT); /*