Index: sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h =================================================================== --- sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h (revision 302306) +++ sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h (working copy) @@ -1716,6 +1716,7 @@ #endif /* ATH_SUPPORT_HTC */ #endif /* ATH_TX99_DIAG */ extern HAL_BOOL ar9300_set_ctl_pwr(struct ath_hal *ah, u_int8_t *ctl_array); +extern u_int32_t ar9300_read_loc_timer_reg(struct ath_hal *ah); extern void ar9300_set_txchainmaskopt(struct ath_hal *ah, u_int8_t mask); enum { Index: sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c =================================================================== --- sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c (revision 302306) +++ sys/contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c (working copy) @@ -2878,7 +2878,6 @@ #if ATH_SUPPORT_SPECTRAL p_cap->halSpectralScanSupport = AH_TRUE; #endif - ahpriv->ah_rfsilent = ar9300_eeprom_get(ahp, EEP_RF_SILENT); if (ahpriv->ah_rfsilent & EEP_RFSILENT_ENABLED) { ahp->ah_gpio_select = MS(ahpriv->ah_rfsilent, EEP_RFSILENT_GPIO_SEL); @@ -2998,8 +2997,8 @@ p_cap->hal_cfend_fix_support = AH_FALSE; p_cap->hal_aggr_extra_delim_war = AH_FALSE; #endif - p_cap->halHasLongRxDescTsf = AH_TRUE; -// p_cap->hal_rx_desc_timestamp_bits = 32; + p_cap->halTxTstampPrecision = 32; + p_cap->halRxTstampPrecision = 32; p_cap->halRxTxAbortSupport = AH_TRUE; p_cap->hal_ani_poll_interval = AR9300_ANI_POLLINTERVAL; p_cap->hal_channel_switch_time_usec = AR9300_CHANNEL_SWITCH_TIME_USEC; Index: sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c =================================================================== --- sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c (revision 302306) +++ sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c (working copy) @@ -26,8 +26,8 @@ #include "ar9300/ar9300.h" #include "ar9300/ar9300reg.h" #include "ar9300/ar9300phy.h" +#include "ar9300/ar9300desc.h" - void ar9300_get_hw_hangs(struct ath_hal *ah, hal_hw_hangs_t *hangs) { @@ -947,6 +947,14 @@ return (HAL_ENOTSUPP); (*result) = !! (ahp->ah_misc_mode & AR_PCU_TXOP_TBTT_LIMIT_ENA); return (HAL_OK); + case HAL_CAP_TOA_LOCATIONING: + if (capability == 0) + return HAL_OK; + if (capability == 2) { + *result = ar9300_read_loc_timer_reg(ah); + return (HAL_OK); + } + return HAL_ENOTSUPP; default: return ath_hal_getcapability(ah, type, capability, result); } @@ -1060,6 +1068,14 @@ } return AH_TRUE; + case HAL_CAP_TOA_LOCATIONING: + if (capability == 0) + return AH_TRUE; + if (capability == 1) { + ar9300_update_loc_ctl_reg(ah, setting); + return AH_TRUE; + } + return AH_FALSE; /* fall thru... */ default: return ath_hal_setcapability(ah, type, capability, setting, status); @@ -3855,6 +3871,13 @@ return AH_FALSE; } +u_int32_t +ar9300_read_loc_timer_reg(struct ath_hal *ah) +{ + + return OS_REG_READ(ah, AR_LOC_TIMER_REG); +} + HAL_BOOL ar9300_set_ctl_pwr(struct ath_hal *ah, u_int8_t *ctl_array) { Index: sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv_ds.c =================================================================== --- sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv_ds.c (revision 302306) +++ sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv_ds.c (working copy) @@ -94,9 +94,16 @@ rxs->rs_moreaggr = (rxsp->status11 & AR_rx_more_aggr) ? 1 : 0; rxs->rs_antenna = (MS(rxsp->status4, AR_rx_antenna) & 0x7); rxs->rs_flags = (rxsp->status11 & AR_apsd_trig) ? HAL_RX_IS_APSD : 0; - rxs->rs_flags |= (rxsp->status4 & AR_gi) ? HAL_RX_GI : 0; - rxs->rs_flags |= (rxsp->status4 & AR_2040) ? HAL_RX_2040 : 0; + rxs->rs_flags |= (rxsp->status4 & AR_gi) ? HAL_RX_GI : 0; + rxs->rs_flags |= (rxsp->status4 & AR_2040) ? HAL_RX_2040 : 0; + /* TX beamforming; CSI for locationing */ + rxs->rs_flags |= (rxsp->status2 & AR_hw_upload_data) ? HAL_RX_HW_UPLOAD_DATA : 0; + rxs->rs_flags |= (rxsp->status4 & AR_rx_not_sounding) ? 0 : HAL_RX_HW_SOUNDING; + rxs->rs_ness = MS(rxsp->status4, AR_rx_ness); + rxs->rs_flags |= (rxsp->status4 & AR_hw_upload_data_valid) ? HAL_RX_UPLOAD_VALID : 0; + rxs->rs_hw_upload_data_type = MS(rxsp->status11, AR_hw_upload_data_type); + /* Copy EVM information */ rxs->rs_evm0 = rxsp->status6; rxs->rs_evm1 = rxsp->status7; @@ -133,9 +140,9 @@ if (rxsp->status11 & AR_crc_err) { rxs->rs_status |= HAL_RXERR_CRC; - /* - * ignore CRC flag for phy reports - */ + /* + * ignore CRC flag for phy reports + */ if (rxsp->status11 & AR_phyerr) { u_int phyerr = MS(rxsp->status11, AR_phy_err_code); rxs->rs_status |= HAL_RXERR_PHY; @@ -164,6 +171,19 @@ } else if (rxsp->status11 & AR_michael_err) { rxs->rs_status |= HAL_RXERR_MIC; } + } else { + if (rxsp->status11 & AR_position_bit) { + /* + * If the locationing counter is enabled, Osprey always + * seems to put AR_position_bit in each frame. + * So, only do this if we also have a valid upload + * and it's type "1" (which I'm guessing is CSI.) + */ + if ((rxs->rs_flags & HAL_RX_UPLOAD_VALID) && + (rxs->rs_hw_upload_data_type == 1)) { + rxs->rs_flags |= HAL_RX_LOC_INFO; + } + } } #if 0 rxs->rs_channel = AH_PRIVATE(ah)->ah_curchan->channel; Index: sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit_ds.c =================================================================== --- sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit_ds.c (revision 302306) +++ sys/contrib/dev/ath/ath_hal/ar9300/ar9300_xmit_ds.c (working copy) @@ -335,6 +335,9 @@ ts->ts_ba_low = ads->status5; ts->ts_ba_high = ads->status6; } + if (ads->status8 & AR_tx_fast_ts) { + ts->ts_flags |= HAL_TX_FAST_TS; + } /* * Extract the transmit rate. @@ -624,6 +627,11 @@ ads->ds_ctl18 = 0; ads->ds_ctl19 = AR_not_sounding; /* set not sounding for normal frame */ + /* ToA/ToD positioning */ + if (flags & HAL_TXDESC_POS) { + ads->ds_ctl12 |= AR_loc_mode; + ads->ds_ctl19 &= ~AR_not_sounding; + } /* * Clear Ness1/2/3 (Number of Extension Spatial Streams) fields. Index: sys/dev/ath/ath_hal/ah.c =================================================================== --- sys/dev/ath/ath_hal/ah.c (revision 302306) +++ sys/dev/ath/ath_hal/ah.c (working copy) @@ -292,6 +292,7 @@ rc = rates->info[rateix].rateCode; /* Legacy rate? Return the old way */ + /* XXX TODO: this returns (incorrect) SIFS time; doesn't add CRC length */ if (! IS_HT_RATE(rc)) return ath_hal_computetxtime(ah, rates, frameLen, rateix, shortPreamble); @@ -301,6 +302,7 @@ ("number of spatial streams needs to be 1..3: MCS rate 0x%x!", rateix)); + /* XXX TODO: this doesn't return any SIFS time at all! */ return ath_computedur_ht(frameLen, rc, numStreams, isht40, shortPreamble); } @@ -354,7 +356,14 @@ { uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime; uint32_t kbps; + int is_2ghz; + /* assume 2ghz unless told otherwise */ + is_2ghz = 1; + if (AH_PRIVATE(ah)->ah_curchan != NULL && + IEEE80211_IS_CHAN_5GHZ(AH_PRIVATE(ah)->ah_curchan)) + is_2ghz = 0; + /* Warn if this function is called for 11n rates; it should not be! */ if (IS_HT_RATE(rates->info[rateix].rateCode)) ath_hal_printf(ah, "%s: MCS rate? (index %d; hwrate 0x%x)\n", @@ -382,9 +391,19 @@ numBits = OFDM_PLCP_BITS + (frameLen << 3); numSymbols = howmany(numBits, bitsPerSymbol); - txTime = OFDM_SIFS_TIME - + OFDM_PREAMBLE_TIME + /* SIFS for 11a is 16uS, for 11bg its 10uS */ + if (is_2ghz) + txTime = 10; + else + txTime = 16; + txTime += OFDM_PREAMBLE_TIME + (numSymbols * OFDM_SYMBOL_TIME); + +#if 1 + /* Not sure why we see the 11g ERP rates need another 2uS.. */ + if (is_2ghz) + txTime += 2; +#endif break; case IEEE80211_T_OFDM_HALF: bitsPerSymbol = (kbps * OFDM_HALF_SYMBOL_TIME) / 1000; @@ -749,7 +768,7 @@ case HAL_CAP_HT20_SGI: return pCap->halHTSGI20Support ? HAL_OK : HAL_ENOTSUPP; case HAL_CAP_RXTSTAMP_PREC: /* rx desc tstamp precision (bits) */ - *result = pCap->halTstampPrecision; + *result = pCap->halRxTstampPrecision; return HAL_OK; case HAL_CAP_ANT_DIV_COMB: /* AR9285/AR9485 LNA diversity */ return pCap->halAntDivCombSupport ? HAL_OK : HAL_ENOTSUPP; @@ -778,8 +797,6 @@ } case HAL_CAP_RXDESC_SELFLINK: /* hardware supports self-linked final RX descriptors correctly */ return pCap->halHasRxSelfLinkedTail ? HAL_OK : HAL_ENOTSUPP; - case HAL_CAP_LONG_RXDESC_TSF: /* 32 bit TSF in RX descriptor? */ - return pCap->halHasLongRxDescTsf ? HAL_OK : HAL_ENOTSUPP; case HAL_CAP_BB_READ_WAR: /* Baseband read WAR */ return pCap->halHasBBReadWar? HAL_OK : HAL_ENOTSUPP; case HAL_CAP_SERIALISE_WAR: /* PCI register serialisation */ @@ -791,6 +808,9 @@ return pCap->halRxUsingLnaMixing ? HAL_OK : HAL_ENOTSUPP; case HAL_CAP_DO_MYBEACON: /* Hardware supports filtering my-beacons */ return pCap->halRxDoMyBeacon ? HAL_OK : HAL_ENOTSUPP; + case HAL_CAP_TXTSTAMP_PREC: /* tx desc tstamp precision (bits) */ + *result = pCap->halTxTstampPrecision; + return HAL_OK; default: return HAL_EINVAL; } Index: sys/dev/ath/ath_hal/ah.h =================================================================== --- sys/dev/ath/ath_hal/ah.h (revision 302306) +++ sys/dev/ath/ath_hal/ah.h (working copy) @@ -194,12 +194,13 @@ HAL_CAP_BSSIDMATCH = 238, /* hardware has disable bssid match */ HAL_CAP_STREAMS = 239, /* how many 802.11n spatial streams are available */ HAL_CAP_RXDESC_SELFLINK = 242, /* support a self-linked tail RX descriptor */ - HAL_CAP_LONG_RXDESC_TSF = 243, /* hardware supports 32bit TSF in RX descriptor */ HAL_CAP_BB_READ_WAR = 244, /* baseband read WAR */ HAL_CAP_SERIALISE_WAR = 245, /* serialise register access on PCI */ HAL_CAP_ENFORCE_TXOP = 246, /* Enforce TXOP if supported */ HAL_CAP_RX_LNA_MIXING = 247, /* RX hardware uses LNA mixing */ HAL_CAP_DO_MYBEACON = 248, /* Supports HAL_RX_FILTER_MYBEACON */ + HAL_CAP_TOA_LOCATIONING = 249, /* time of flight / arrival locationing */ + HAL_CAP_TXTSTAMP_PREC = 250, /* tx desc tstamp precision (bits) */ } HAL_CAPABILITY_TYPE; /* Index: sys/dev/ath/ath_hal/ah_desc.h =================================================================== --- sys/dev/ath/ath_hal/ah_desc.h (revision 302306) +++ sys/dev/ath/ath_hal/ah_desc.h (working copy) @@ -46,7 +46,8 @@ */ struct ath_tx_status { uint16_t ts_seqnum; /* h/w assigned sequence number */ - uint16_t ts_tstamp; /* h/w assigned timestamp */ + uint16_t ts_pad1[1]; + uint32_t ts_tstamp; /* h/w assigned timestamp */ uint8_t ts_status; /* frame status, 0 => xmit ok */ uint8_t ts_rate; /* h/w transmit rate index */ int8_t ts_rssi; /* tx ack RSSI */ @@ -86,6 +87,7 @@ #define HAL_TX_DESC_CFG_ERR 0x10 /* Error in 20/40 desc config */ #define HAL_TX_DATA_UNDERRUN 0x20 /* Tx buffer underrun */ #define HAL_TX_DELIM_UNDERRUN 0x40 /* Tx delimiter underrun */ +#define HAL_TX_FAST_TS 0x80 /* Tx locationing timestamp */ /* * Receive descriptor status. This structure is filled @@ -128,6 +130,9 @@ uint16_t rs_flags; /* misc flags */ uint8_t rs_num_delims; /* number of delims in aggr */ uint8_t rs_spare0; /* padding */ + uint8_t rs_ness; /* number of extension spatial streams */ + uint8_t rs_hw_upload_data_type; /* hw upload format */ + uint16_t rs_spare1; uint32_t rs_evm0; /* evm bytes */ uint32_t rs_evm1; uint32_t rs_evm2; @@ -156,7 +161,12 @@ #define HAL_RX_HI_RX_CHAIN 0x0080 /* SM power save: hi Rx chain control */ #define HAL_RX_IS_APSD 0x0100 /* Is ASPD trigger frame */ #define HAL_RX_STBC 0x0200 /* Is an STBC frame */ +#define HAL_RX_LOC_INFO 0x0400 /* RX locationing information */ +#define HAL_RX_HW_UPLOAD_DATA 0x1000 +#define HAL_RX_HW_SOUNDING 0x2000 +#define HAL_RX_UPLOAD_VALID 0x4000 + /* * This is the format of RSSI[2] on the AR9285/AR9485. * It encodes the LNA configuration information. @@ -282,6 +292,7 @@ #define HAL_TXDESC_LOWRXCHAIN 0x0400 /* switch to low RX chain */ #define HAL_TXDESC_LDPC 0x1000 /* Set LDPC TX for all rates */ #define HAL_TXDESC_HWTS 0x2000 /* Request Azimuth Timestamp in TX payload */ +#define HAL_TXDESC_POS 0x4000 /* Request ToD/ToA locationing */ /* flags passed to rx descriptor setup methods */ #define HAL_RXDESC_INTREQ 0x0020 /* enable per-descriptor interrupt */ Index: sys/dev/ath/ath_hal/ah_internal.h =================================================================== --- sys/dev/ath/ath_hal/ah_internal.h (revision 302306) +++ sys/dev/ath/ath_hal/ah_internal.h (working copy) @@ -260,7 +260,6 @@ hal4kbSplitTransSupport : 1, halHasRxSelfLinkedTail : 1, halSupportsFastClock5GHz : 1, - halHasLongRxDescTsf : 1, halHasBBReadWar : 1, halSerialiseRegWar : 1, halMciSupport : 1, @@ -290,7 +289,8 @@ uint16_t halKeyCacheSize; uint16_t halLow5GhzChan, halHigh5GhzChan; uint16_t halLow2GhzChan, halHigh2GhzChan; - int halTstampPrecision; + int halTxTstampPrecision; + int halRxTstampPrecision; int halRtsAggrLimit; uint8_t halTxChainMask; uint8_t halRxChainMask; Index: sys/dev/ath/ath_hal/ar5210/ar5210_attach.c =================================================================== --- sys/dev/ath/ath_hal/ar5210/ar5210_attach.c (revision 302306) +++ sys/dev/ath/ath_hal/ar5210/ar5210_attach.c (working copy) @@ -390,7 +390,8 @@ pCap->halRfSilentSupport = AH_TRUE; } - pCap->halTstampPrecision = 15; /* NB: s/w extended from 13 */ + pCap->halTxTstampPrecision = 16; + pCap->halRxTstampPrecision = 15; /* NB: s/w extended from 13 */ pCap->halIntrMask = (HAL_INT_COMMON - HAL_INT_BNR) | HAL_INT_RX | HAL_INT_TX Index: sys/dev/ath/ath_hal/ar5211/ar5211_attach.c =================================================================== --- sys/dev/ath/ath_hal/ar5211/ar5211_attach.c (revision 302306) +++ sys/dev/ath/ath_hal/ar5211/ar5211_attach.c (working copy) @@ -520,7 +520,8 @@ pCap->halRfSilentSupport = AH_TRUE; } - pCap->halTstampPrecision = 13; + pCap->halRxTstampPrecision = 13; + pCap->halTxTstampPrecision = 16; pCap->halIntrMask = HAL_INT_COMMON | HAL_INT_RX | HAL_INT_TX Index: sys/dev/ath/ath_hal/ar5212/ar5212_attach.c =================================================================== --- sys/dev/ath/ath_hal/ar5212/ar5212_attach.c (revision 302306) +++ sys/dev/ath/ath_hal/ar5212/ar5212_attach.c (working copy) @@ -899,7 +899,8 @@ pCap->halBssidMatchSupport = AH_TRUE; } - pCap->halTstampPrecision = 15; + pCap->halRxTstampPrecision = 15; + pCap->halTxTstampPrecision = 16; pCap->halIntrMask = HAL_INT_COMMON | HAL_INT_RX | HAL_INT_TX Index: sys/dev/ath/ath_hal/ar5416/ar5416_attach.c =================================================================== --- sys/dev/ath/ath_hal/ar5416/ar5416_attach.c (revision 302306) +++ sys/dev/ath/ath_hal/ar5416/ar5416_attach.c (working copy) @@ -967,7 +967,8 @@ pCap->halChanHalfRate = AH_TRUE; pCap->halChanQuarterRate = AH_TRUE; - pCap->halTstampPrecision = 32; + pCap->halTxTstampPrecision = 32; + pCap->halRxTstampPrecision = 32; pCap->halHwPhyCounterSupport = AH_TRUE; pCap->halIntrMask = HAL_INT_COMMON | HAL_INT_RX @@ -1019,8 +1020,6 @@ pCap->halGTTSupport = AH_TRUE; pCap->halCSTSupport = AH_TRUE; pCap->halEnhancedDfsSupport = AH_FALSE; - /* Hardware supports 32 bit TSF values in the RX descriptor */ - pCap->halHasLongRxDescTsf = AH_TRUE; /* * BB Read WAR: this is only for AR5008/AR9001 NICs * It is also set individually in the AR91xx attach functions. Index: sys/dev/ath/if_ath.c =================================================================== --- sys/dev/ath/if_ath.c (revision 302306) +++ sys/dev/ath/if_ath.c (working copy) @@ -128,6 +128,8 @@ #include #endif +#include + /* * Only enable this if you're working on PS-POLL support. */ @@ -971,7 +973,18 @@ sc->sc_hasbmatch = ath_hal_hasbssidmatch(ah); sc->sc_hastsfadd = ath_hal_hastsfadjust(ah); sc->sc_rxslink = ath_hal_self_linked_final_rxdesc(ah); - sc->sc_rxtsf32 = ath_hal_has_long_rxdesc_tsf(ah); + + /* XXX TODO: just make this a "store tx/rx timestamp length" operation */ + if (ath_hal_get_rx_tsf_prec(ah, &i)) { + if (i == 32) { + sc->sc_rxtsf32 = 1; + } + device_printf(sc->sc_dev, "RX timestamp: %d bits\n", i); + } + if (ath_hal_get_tx_tsf_prec(ah, &i)) { + device_printf(sc->sc_dev, "TX timestamp: %d bits\n", i); + } + sc->sc_hasenforcetxop = ath_hal_hasenforcetxop(ah); sc->sc_rx_lnamixer = ath_hal_hasrxlnamixer(ah); sc->sc_hasdivcomb = ath_hal_hasdivantcomb(ah); @@ -1953,6 +1966,9 @@ */ ath_btcoex_enable(sc, ic->ic_curchan); + /* TOA positioning */ + ath_hal_setcapability(sc->sc_ah, HAL_CAP_TOA_LOCATIONING, 1, 1, NULL); + /* * If we're doing TDMA, enforce the TXOP limitation for chips that * support it. @@ -2494,6 +2510,9 @@ */ ath_btcoex_enable(sc, ic->ic_curchan); + /* TOA positioning */ + ath_hal_setcapability(sc->sc_ah, HAL_CAP_TOA_LOCATIONING, 1, 1, NULL); + /* * If we're doing TDMA, enforce the TXOP limitation for chips that * support it. @@ -2873,6 +2892,9 @@ */ ath_btcoex_enable(sc, ic->ic_curchan); + /* TOA positioning */ + ath_hal_setcapability(sc->sc_ah, HAL_CAP_TOA_LOCATIONING, 1, 1, NULL); + /* * If we're doing TDMA, enforce the TXOP limitation for chips that * support it. @@ -4218,6 +4240,11 @@ ath_tx_update_stats(sc, ts, bf); } + /* If it's marked as a location frame; print the timestamp */ + if (ts->ts_flags & HAL_TX_FAST_TS) { + ath_location_process_tx_complete(sc, txq, ts, bf); + } + /* * Call the completion handler. * The completion handler is responsible for @@ -5165,6 +5192,9 @@ */ ath_btcoex_enable(sc, ic->ic_curchan); + /* TOA positioning */ + ath_hal_setcapability(sc->sc_ah, HAL_CAP_TOA_LOCATIONING, 1, 1, NULL); + /* * If we're doing TDMA, enforce the TXOP limitation for chips * that support it. Index: sys/dev/ath/if_ath_location.c =================================================================== --- sys/dev/ath/if_ath_location.c (nonexistent) +++ sys/dev/ath/if_ath_location.c (working copy) @@ -0,0 +1,271 @@ +/*- + * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * Driver for the Atheros Wireless LAN controller. + * + * This software is derived from work of Atsushi Onoe; his contribution + * is greatly appreciated. + */ + +#include "opt_inet.h" +#include "opt_ath.h" +/* + * This is needed for register operations which are performed + * by the driver - eg, calls to ath_hal_gettsf32(). + * + * It's also required for any AH_DEBUG checks in here, eg the + * module dependencies. + */ +#include "opt_ah.h" +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for mp_ncpus */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#ifdef IEEE80211_SUPPORT_SUPERG +#include +#endif +#ifdef IEEE80211_SUPPORT_TDMA +#include +#endif + +#include + +#ifdef INET +#include +#include +#endif + +#include +#include /* XXX for softled */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef ATH_TX99_DIAG +#include +#endif + +#ifdef ATH_DEBUG_ALQ +#include +#endif + +#include + +/* XXX total hack */ +static uint32_t last_rx_ts = 0; +static uint32_t last_rx_ts_dur = 0; + +void +ath_location_process_rx_complete(struct ath_softc *sc, struct ath_rx_status *rs, + uint64_t tsf, struct mbuf *m, struct ath_buf *bf) +{ + uint32_t dur, pkt_dur; + const HAL_RATE_TABLE *rt = sc->sc_currates; + int rix; + + rix = rt->rateCodeToIndex[rs->rs_rate]; + + /* Let's do some quick math */ + dur = rs->rs_tstamp; /* in clock cycles; which should be 44MHz */ + pkt_dur = ath_hal_pkt_txtime(sc->sc_ah, rt, + 14, /* 10 byte ACK, 4 byte CRC */ + rix, + !! (rs->rs_flags & HAL_RX_2040), + (rs->rs_rate & 0x80) ? + (rs->rs_flags & HAL_RX_GI) : rt->info[rix].shortPreamble); + device_printf(sc->sc_dev, "%s: ACK RX; ts=%u, dur=%u, startts=%u\n", + __func__, + dur, pkt_dur, dur - (pkt_dur * 44)); + last_rx_ts = dur; + last_rx_ts_dur = pkt_dur; + /* Process RX location events */ + device_printf(sc->sc_dev, + "%s: RX location info: tsf=%llu, ts=%u, flags=0x%08x, ness=%d, upload_type=%d, rate=0x%02x\n", + __func__, + (unsigned long long) tsf, + (unsigned int) rs->rs_tstamp, + rs->rs_flags, + rs->rs_ness, + rs->rs_hw_upload_data_type, + rs->rs_rate); +#if 0 + if (rs->rs_hw_upload_data_type == 1) { + ath_printrxbuf(sc, bf, 0, 1); + m_print(m, rs->rs_datalen); + } +#endif +} + +extern u_int ath_hal_mac_clks(struct ath_hal *ah, u_int usecs); + +void +ath_location_process_tx_complete(struct ath_softc *sc, struct ath_txq *txq, + struct ath_tx_status *ts, struct ath_buf *bf) +{ + uint32_t dur, pkt_dur; + const HAL_RATE_TABLE *rt = sc->sc_currates; + int rix; + struct ath_rc_series *rc; + + if (! ts->ts_flags & HAL_TX_FAST_TS) + return; + + + rix = rt->rateCodeToIndex[ts->ts_rate]; + rc = &bf->bf_state.bfs_rc[ts->ts_finaltsi]; + + /* Let's do some quick math */ + dur = ts->ts_tstamp; /* in clock cycles; which should be 44MHz */ + + pkt_dur = ath_hal_pkt_txtime(sc->sc_ah, rt, + bf->bf_state.bfs_pktlen, /* assume non-aggregate; CRC is included */ + rix, + !! (rc->flags & ATH_RC_CW40_FLAG), + ts->ts_rate & 0x80 ? + (rc->flags & ATH_RC_SGI_FLAG) + : rt->info[rix].shortPreamble); + + /* XXX hack! */ + if (last_rx_ts != 0) { + uint32_t clk; + int c, cc; + int nu, de; + + clk = last_rx_ts - dur; + + device_printf(sc->sc_dev, "%s: position completion: " + "txstamp=%u, rxstamp=%u, txrate=0x%02x, " + "txdur=%u, rxdur=%u, txlen=%d, shortgi=%d, " + "delta=%d (%d nsec)\n", + __func__, + dur, + last_rx_ts, + ts->ts_rate, + pkt_dur, + last_rx_ts_dur, + bf->bf_state.bfs_pktlen, + !! (rc->flags & ATH_RC_SGI_FLAG), + (int) clk, + (int) clk * 23); + + /* + * XXX TODO: figure it out! + * + * There's a SIFS between the NULL sending and the + * ACK generation, but there's no SIFS we need + * to worry about /after/ the ACK generation. + * Now, the txtime calculation from ath_hal + * adds SIFS (incorrectly except in a local change) + * for 11abg rates, and doesn't add it for 11n + * rates. + * + * Now, I thought the whole exchange wouldn't need + * to include SIFS for both ACK /and/ the NULL frame + * but the delta returned by the hardware /seems/ + * to want it. I'm not sure why; it warrants + * investigation. It may be that asserting TXFRAME + * happens before the SIFS countdown, which would + * explain it. + * + * Yes, we should fix this later in a more generic + * way. + */ + + c = ath_hal_mac_clks(sc->sc_ah, pkt_dur) + + ath_hal_mac_clks(sc->sc_ah, last_rx_ts_dur); + cc = (clk - c) * 22728; /* 22.7272.. nsec; 44MHz */ + + nu = cc / 1000; + de = cc % 1000; + device_printf(sc->sc_dev, "%s: delta=%u, c=%d, result=%d (%d.%04d nsec)\n", + __func__, + clk, + c, + clk - c, + nu, + de); + + + last_rx_ts = 0; + last_rx_ts_dur = 0; + } +} Property changes on: sys/dev/ath/if_ath_location.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: sys/dev/ath/if_ath_location.h =================================================================== --- sys/dev/ath/if_ath_location.h (nonexistent) +++ sys/dev/ath/if_ath_location.h (working copy) @@ -0,0 +1,10 @@ +#ifndef __IF_ATH_LOCATION_H__ +#define __IF_ATH_LOCATION_H__ + +extern void ath_location_process_rx_complete(struct ath_softc *sc, + struct ath_rx_status *rs, uint64_t tsf, struct mbuf *m, + struct ath_buf *bf); +extern void ath_location_process_tx_complete(struct ath_softc *sc, + struct ath_txq *txq, struct ath_tx_status *ts, struct ath_buf *bf); + +#endif Property changes on: sys/dev/ath/if_ath_location.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: sys/dev/ath/if_ath_rx.c =================================================================== --- sys/dev/ath/if_ath_rx.c (revision 302306) +++ sys/dev/ath/if_ath_rx.c (working copy) @@ -123,6 +123,8 @@ #include +#include + /* * Calculate the receive filter according to the * operating mode and state: @@ -543,6 +545,9 @@ } else { sc->sc_rx_th.wr_v.vh_phyerr_code = 0xff; } + + /* XXX location info? */ + sc->sc_rx_th.wr_v.vh_rs_status = rs->rs_status; sc->sc_rx_th.wr_v.vh_rssi = rs->rs_rssi; } @@ -587,7 +592,7 @@ sc->sc_rx_th.wr_chan_flags |= CHAN_HT40U; else sc->sc_rx_th.wr_chan_flags |= CHAN_HT40D; - if ((rs->rs_flags & HAL_RX_GI) == 0) + if (rs->rs_flags & HAL_RX_GI) sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTGI; } @@ -752,6 +757,14 @@ m_freem(m); m = NULL; goto rx_next; } + + /* Location CSI reports */ + if (rs->rs_flags & HAL_RX_LOC_INFO) { + ath_location_process_rx_complete(sc, rs, tsf, m, bf); + /* XXX we should drop this frame, it's not a valid payload */ + goto rx_error; + } + rx_accept: len = rs->rs_datalen; m->m_len = len; Index: sys/dev/ath/if_ath_tdma.c =================================================================== --- sys/dev/ath/if_ath_tdma.c (revision 302306) +++ sys/dev/ath/if_ath_tdma.c (working copy) @@ -429,8 +429,8 @@ txtime = ath_hal_pkt_txtime(ah, rt, rs->rs_datalen, rix, !! (rs->rs_flags & HAL_RX_2040), - (rix & 0x80) ? - (! (rs->rs_flags & HAL_RX_GI)) : rt->info[rix].shortPreamble); + (rs->rs_rate & 0x80) ? + (!! (rs->rs_flags & HAL_RX_GI)) : rt->info[rix].shortPreamble); /* NB: << 9 is to cvt to TU and /2 */ nextslot = (rstamp - txtime) + (sc->sc_tdmabintval << 9); Index: sys/dev/ath/if_ath_tx.c =================================================================== --- sys/dev/ath/if_ath_tx.c (revision 302306) +++ sys/dev/ath/if_ath_tx.c (working copy) @@ -1042,6 +1042,14 @@ shortPreamble = bf->bf_state.bfs_shpream; wh = mtod(bf->bf_m, struct ieee80211_frame *); + /* Disable frame protection for TOA probe frames */ + if (bf->bf_flags & ATH_BUF_TOA_PROBE) { + /* XXX count */ + flags &= ~(HAL_TXDESC_CTSENA | HAL_TXDESC_RTSENA); + bf->bf_state.bfs_doprot = 0; + goto finish; + } + /* * If 802.11g protection is enabled, determine whether * to use RTS/CTS or just CTS. Note that this is only @@ -1081,6 +1089,8 @@ flags |= HAL_TXDESC_RTSENA; sc->sc_stats.ast_tx_htprotect++; } + +finish: bf->bf_state.bfs_txflags = flags; } @@ -1738,6 +1748,34 @@ } #endif + /* + * If it's a frame to do location reporting on, + * communicate it to the HAL. + */ + if (ieee80211_get_toa_params(m0, NULL)) { + device_printf(sc->sc_dev, + "%s: setting TX positioning bit\n", __func__); + flags |= HAL_TXDESC_POS; + + /* + * Note: The hardware reports timestamps for + * each of the RX'ed packets as part of the packet + * exchange. So this means things like RTS/CTS + * exchanges, as well as the final ACK. + * + * So, if you send a RTS-protected NULL data frame, + * you'll get an RX report for the RTS response, then + * an RX report for the NULL frame, and then the TX + * completion at the end. + * + * NOTE: it doesn't work right for CCK frames; + * there's no channel info data provided unless + * it's OFDM or HT. Will have to dig into it. + */ + flags &= ~(HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA); + bf->bf_flags |= ATH_BUF_TOA_PROBE; + } + #if 0 /* * Placeholder: if you want to transmit with the azimuth @@ -1782,6 +1820,7 @@ ieee80211_dump_pkt(ic, mtod(m0, const uint8_t *), m0->m_len, sc->sc_hwmap[rix].ieeerate, -1); + /* XXX TODO: use the packet duration and completion tsf.. */ if (ieee80211_radiotap_active_vap(vap)) { u_int64_t tsf = ath_hal_gettsf64(ah); @@ -2174,6 +2213,18 @@ try0 = ATH_TXMAXTRY; /* XXX?too many? */ } + /* + * If it's a frame to do location reporting on, + * communicate it to the HAL. + */ + if (ieee80211_get_toa_params(m0, NULL)) { + device_printf(sc->sc_dev, + "%s: setting TX positioning bit\n", __func__); + flags |= HAL_TXDESC_POS; + flags &= ~(HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA); + bf->bf_flags |= ATH_BUF_TOA_PROBE; + } + txrate = rt->info[rix].rateCode; if (params->ibp_flags & IEEE80211_BPF_SHORTPRE) txrate |= rt->info[rix].shortPreamble; @@ -2200,6 +2251,7 @@ ieee80211_dump_pkt(ic, mtod(m0, caddr_t), m0->m_len, sc->sc_hwmap[rix].ieeerate, -1); + /* XXX TODO: use the packet duration and completion tsf.. */ if (ieee80211_radiotap_active_vap(vap)) { u_int64_t tsf = ath_hal_gettsf64(ah); Index: sys/dev/ath/if_ath_tx_edma.c =================================================================== --- sys/dev/ath/if_ath_tx_edma.c (revision 302306) +++ sys/dev/ath/if_ath_tx_edma.c (working copy) @@ -268,7 +268,7 @@ /* Bump FIFO queue */ txq->axq_fifo_depth++; - DPRINTF(sc, ATH_DEBUG_XMIT, + DPRINTF(sc, ATH_DEBUG_XMIT | ATH_DEBUG_TX_PROC, "%s: queued %d packets; depth=%d, fifo depth=%d\n", __func__, sqdepth, txq->fifo.axq_depth, txq->axq_fifo_depth); @@ -296,16 +296,21 @@ ATH_TXQ_LOCK_ASSERT(txq); - DPRINTF(sc, ATH_DEBUG_TX_PROC, "%s: Q%d: called\n", + DPRINTF(sc, ATH_DEBUG_TX_PROC, + "%s: Q%d: called; fifo.depth=%d, fifo depth=%d, depth=%d, aggr_depth=%d\n", __func__, - txq->axq_qnum); + txq->axq_qnum, + txq->fifo.axq_depth, + txq->axq_fifo_depth, + txq->axq_depth, + txq->axq_aggr_depth); /* - * For now, push up to 4 frames per TX FIFO slot. + * For now, push up to 32 frames per TX FIFO slot. * If more are in the hardware queue then they'll * get populated when we try to send another frame * or complete a frame - so at most there'll be - * 32 non-AMPDU frames per TXQ. + * 32 non-AMPDU frames per node/TID anyway. * * Note that the hardware staging queue will limit * how many frames in total we will have pushed into @@ -811,10 +816,11 @@ } #if defined(ATH_DEBUG_ALQ) && defined(ATH_DEBUG) - if (if_ath_alq_checkdebug(&sc->sc_alq, ATH_ALQ_EDMA_TXSTATUS)) + if (if_ath_alq_checkdebug(&sc->sc_alq, ATH_ALQ_EDMA_TXSTATUS)) { if_ath_alq_post(&sc->sc_alq, ATH_ALQ_EDMA_TXSTATUS, sc->sc_tx_statuslen, (char *) txstatus); + } #endif /* ATH_DEBUG_ALQ */ /* Index: sys/dev/ath/if_ath_tx_ht.c =================================================================== --- sys/dev/ath/if_ath_tx_ht.c (revision 302306) +++ sys/dev/ath/if_ath_tx_ht.c (working copy) @@ -222,6 +222,7 @@ ath_tx_rate_fill_rcflags(struct ath_softc *sc, struct ath_buf *bf) { struct ieee80211_node *ni = bf->bf_node; + struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = ni->ni_ic; const HAL_RATE_TABLE *rt = sc->sc_currates; struct ath_rc_series *rc = bf->bf_state.bfs_rc; @@ -280,12 +281,14 @@ if (ni->ni_chw == 40 && ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 && - ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40) + ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40 && + vap->iv_flags_ht & IEEE80211_FHT_SHORTGI40) rc[i].flags |= ATH_RC_SGI_FLAG; if (ni->ni_chw == 20 && ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 && - ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20) + ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20 && + vap->iv_flags_ht & IEEE80211_FHT_SHORTGI20) rc[i].flags |= ATH_RC_SGI_FLAG; /* Index: sys/dev/ath/if_athvar.h =================================================================== --- sys/dev/ath/if_athvar.h (revision 302306) +++ sys/dev/ath/if_athvar.h (working copy) @@ -314,8 +314,9 @@ #define ATH_BUF_BUSY 0x00000002 /* (tx) desc owned by h/w */ #define ATH_BUF_FIFOEND 0x00000004 #define ATH_BUF_FIFOPTR 0x00000008 +#define ATH_BUF_TOA_PROBE 0x00000010 /* ToD/ToA exchange probe */ -#define ATH_BUF_FLAGS_CLONE (ATH_BUF_MGMT) +#define ATH_BUF_FLAGS_CLONE (ATH_BUF_MGMT | ATH_BUF_TOA_PROBE) /* * DMA state for tx/rx descriptors. @@ -1370,9 +1371,12 @@ 0, NULL) == HAL_OK) #define ath_hal_gtxto_supported(_ah) \ (ath_hal_getcapability(_ah, HAL_CAP_GTXTO, 0, NULL) == HAL_OK) -#define ath_hal_has_long_rxdesc_tsf(_ah) \ - (ath_hal_getcapability(_ah, HAL_CAP_LONG_RXDESC_TSF, \ - 0, NULL) == HAL_OK) +#define ath_hal_get_rx_tsf_prec(_ah, _pr) \ + (ath_hal_getcapability((_ah), HAL_CAP_RXTSTAMP_PREC, 0, (_pr)) \ + == HAL_OK) +#define ath_hal_get_tx_tsf_prec(_ah, _pr) \ + (ath_hal_getcapability((_ah), HAL_CAP_TXTSTAMP_PREC, 0, (_pr)) \ + == HAL_OK) #define ath_hal_setuprxdesc(_ah, _ds, _size, _intreq) \ ((*(_ah)->ah_setupRxDesc)((_ah), (_ds), (_size), (_intreq))) #define ath_hal_rxprocdesc(_ah, _ds, _dspa, _dsnext, _rs) \