Break out the radar code into a separate source file.
This mirrors the internal HAL organisation and reduces the differences between the HAL codebases slightly. Obtained from: Atheros
This commit is contained in:
parent
033892980c
commit
7b1144d245
@ -773,6 +773,10 @@ dev/ath/ath_hal/ar5416/ar5416_power.c \
|
||||
optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \
|
||||
ath_ar9287 \
|
||||
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
|
||||
dev/ath/ath_hal/ar5416/ar5416_radar.c \
|
||||
optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \
|
||||
ath_ar9287 \
|
||||
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
|
||||
dev/ath/ath_hal/ar5416/ar5416_recv.c \
|
||||
optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \
|
||||
ath_ar9287 \
|
||||
|
@ -215,6 +215,7 @@ extern HAL_BOOL ar5416GetDiagState(struct ath_hal *ah, int request,
|
||||
void **result, uint32_t *resultsize);
|
||||
extern HAL_BOOL ar5416SetRifsDelay(struct ath_hal *ah,
|
||||
const struct ieee80211_channel *chan, HAL_BOOL enable);
|
||||
|
||||
extern void ar5416EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe);
|
||||
extern void ar5416GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe);
|
||||
extern HAL_BOOL ar5416ProcessRadarEvent(struct ath_hal *ah,
|
||||
|
@ -720,361 +720,3 @@ ar5416DetectBBHang(struct ath_hal *ah)
|
||||
#undef N
|
||||
}
|
||||
#undef NUM_STATUS_READS
|
||||
|
||||
/*
|
||||
* Get the radar parameter values and return them in the pe
|
||||
* structure
|
||||
*/
|
||||
void
|
||||
ar5416GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
|
||||
{
|
||||
uint32_t val, temp;
|
||||
|
||||
val = OS_REG_READ(ah, AR_PHY_RADAR_0);
|
||||
|
||||
temp = MS(val,AR_PHY_RADAR_0_FIRPWR);
|
||||
temp |= 0xFFFFFF80;
|
||||
pe->pe_firpwr = temp;
|
||||
pe->pe_rrssi = MS(val, AR_PHY_RADAR_0_RRSSI);
|
||||
pe->pe_height = MS(val, AR_PHY_RADAR_0_HEIGHT);
|
||||
pe->pe_prssi = MS(val, AR_PHY_RADAR_0_PRSSI);
|
||||
pe->pe_inband = MS(val, AR_PHY_RADAR_0_INBAND);
|
||||
|
||||
/* RADAR_1 values */
|
||||
val = OS_REG_READ(ah, AR_PHY_RADAR_1);
|
||||
pe->pe_relpwr = MS(val, AR_PHY_RADAR_1_RELPWR_THRESH);
|
||||
pe->pe_relstep = MS(val, AR_PHY_RADAR_1_RELSTEP_THRESH);
|
||||
pe->pe_maxlen = MS(val, AR_PHY_RADAR_1_MAXLEN);
|
||||
|
||||
pe->pe_extchannel = !! (OS_REG_READ(ah, AR_PHY_RADAR_EXT) &
|
||||
AR_PHY_RADAR_EXT_ENA);
|
||||
|
||||
pe->pe_usefir128 = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
|
||||
AR_PHY_RADAR_1_USE_FIR128);
|
||||
pe->pe_blockradar = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
|
||||
AR_PHY_RADAR_1_BLOCK_CHECK);
|
||||
pe->pe_enmaxrssi = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
|
||||
AR_PHY_RADAR_1_MAX_RRSSI);
|
||||
pe->pe_enabled = !!
|
||||
(OS_REG_READ(ah, AR_PHY_RADAR_0) & AR_PHY_RADAR_0_ENA);
|
||||
pe->pe_enrelpwr = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
|
||||
AR_PHY_RADAR_1_RELPWR_ENA);
|
||||
pe->pe_en_relstep_check = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
|
||||
AR_PHY_RADAR_1_RELSTEP_CHECK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable radar detection and set the radar parameters per the
|
||||
* values in pe
|
||||
*/
|
||||
void
|
||||
ar5416EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = OS_REG_READ(ah, AR_PHY_RADAR_0);
|
||||
|
||||
if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) {
|
||||
val &= ~AR_PHY_RADAR_0_FIRPWR;
|
||||
val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR);
|
||||
}
|
||||
if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) {
|
||||
val &= ~AR_PHY_RADAR_0_RRSSI;
|
||||
val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI);
|
||||
}
|
||||
if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) {
|
||||
val &= ~AR_PHY_RADAR_0_HEIGHT;
|
||||
val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT);
|
||||
}
|
||||
if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) {
|
||||
val &= ~AR_PHY_RADAR_0_PRSSI;
|
||||
val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI);
|
||||
}
|
||||
if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) {
|
||||
val &= ~AR_PHY_RADAR_0_INBAND;
|
||||
val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND);
|
||||
}
|
||||
|
||||
/*Enable FFT data*/
|
||||
val |= AR_PHY_RADAR_0_FFT_ENA;
|
||||
OS_REG_WRITE(ah, AR_PHY_RADAR_0, val);
|
||||
|
||||
/* Implicitly enable */
|
||||
if (pe->pe_enabled == 1)
|
||||
OS_REG_SET_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA);
|
||||
else if (pe->pe_enabled == 0)
|
||||
OS_REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA);
|
||||
|
||||
if (pe->pe_usefir128 == 1)
|
||||
OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_USE_FIR128);
|
||||
else if (pe->pe_usefir128 == 0)
|
||||
OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_USE_FIR128);
|
||||
|
||||
if (pe->pe_enmaxrssi == 1)
|
||||
OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_MAX_RRSSI);
|
||||
else if (pe->pe_enmaxrssi == 0)
|
||||
OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_MAX_RRSSI);
|
||||
|
||||
if (pe->pe_blockradar == 1)
|
||||
OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_BLOCK_CHECK);
|
||||
else if (pe->pe_blockradar == 0)
|
||||
OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_BLOCK_CHECK);
|
||||
|
||||
if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL) {
|
||||
val = OS_REG_READ(ah, AR_PHY_RADAR_1);
|
||||
val &= ~AR_PHY_RADAR_1_RELSTEP_THRESH;
|
||||
val |= SM(pe->pe_relstep, AR_PHY_RADAR_1_RELSTEP_THRESH);
|
||||
OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);
|
||||
}
|
||||
if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL) {
|
||||
val = OS_REG_READ(ah, AR_PHY_RADAR_1);
|
||||
val &= ~AR_PHY_RADAR_1_RELPWR_THRESH;
|
||||
val |= SM(pe->pe_relpwr, AR_PHY_RADAR_1_RELPWR_THRESH);
|
||||
OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);
|
||||
}
|
||||
|
||||
if (pe->pe_en_relstep_check == 1)
|
||||
OS_REG_SET_BIT(ah, AR_PHY_RADAR_1,
|
||||
AR_PHY_RADAR_1_RELSTEP_CHECK);
|
||||
else if (pe->pe_en_relstep_check == 0)
|
||||
OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1,
|
||||
AR_PHY_RADAR_1_RELSTEP_CHECK);
|
||||
|
||||
if (pe->pe_enrelpwr == 1)
|
||||
OS_REG_SET_BIT(ah, AR_PHY_RADAR_1,
|
||||
AR_PHY_RADAR_1_RELPWR_ENA);
|
||||
else if (pe->pe_enrelpwr == 0)
|
||||
OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1,
|
||||
AR_PHY_RADAR_1_RELPWR_ENA);
|
||||
|
||||
if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL) {
|
||||
val = OS_REG_READ(ah, AR_PHY_RADAR_1);
|
||||
val &= ~AR_PHY_RADAR_1_MAXLEN;
|
||||
val |= SM(pe->pe_maxlen, AR_PHY_RADAR_1_MAXLEN);
|
||||
OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable HT/40 if the upper layer asks;
|
||||
* it should check the channel is HT/40 and HAL_CAP_EXT_CHAN_DFS
|
||||
* is available.
|
||||
*/
|
||||
if (pe->pe_extchannel == 1)
|
||||
OS_REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
|
||||
else if (pe->pe_extchannel == 0)
|
||||
OS_REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract the radar event information from the given phy error.
|
||||
*
|
||||
* Returns AH_TRUE if the phy error was actually a phy error,
|
||||
* AH_FALSE if the phy error wasn't a phy error.
|
||||
*/
|
||||
|
||||
/* Flags for pulse_bw_info */
|
||||
#define PRI_CH_RADAR_FOUND 0x01
|
||||
#define EXT_CH_RADAR_FOUND 0x02
|
||||
#define EXT_CH_RADAR_EARLY_FOUND 0x04
|
||||
|
||||
HAL_BOOL
|
||||
ar5416ProcessRadarEvent(struct ath_hal *ah, struct ath_rx_status *rxs,
|
||||
uint64_t fulltsf, const char *buf, HAL_DFS_EVENT *event)
|
||||
{
|
||||
HAL_BOOL doDfsExtCh;
|
||||
HAL_BOOL doDfsEnhanced;
|
||||
HAL_BOOL doDfsCombinedRssi;
|
||||
|
||||
uint8_t rssi = 0, ext_rssi = 0;
|
||||
uint8_t pulse_bw_info = 0, pulse_length_ext = 0, pulse_length_pri = 0;
|
||||
uint32_t dur = 0;
|
||||
int pri_found = 1, ext_found = 0;
|
||||
int early_ext = 0;
|
||||
int is_dc = 0;
|
||||
uint16_t datalen; /* length from the RX status field */
|
||||
|
||||
/* Check whether the given phy error is a radar event */
|
||||
if ((rxs->rs_phyerr != HAL_PHYERR_RADAR) &&
|
||||
(rxs->rs_phyerr != HAL_PHYERR_FALSE_RADAR_EXT)) {
|
||||
return AH_FALSE;
|
||||
}
|
||||
|
||||
/* Grab copies of the capabilities; just to make the code clearer */
|
||||
doDfsExtCh = AH_PRIVATE(ah)->ah_caps.halExtChanDfsSupport;
|
||||
doDfsEnhanced = AH_PRIVATE(ah)->ah_caps.halEnhancedDfsSupport;
|
||||
doDfsCombinedRssi = AH_PRIVATE(ah)->ah_caps.halUseCombinedRadarRssi;
|
||||
|
||||
datalen = rxs->rs_datalen;
|
||||
|
||||
/* If hardware supports it, use combined RSSI, else use chain 0 RSSI */
|
||||
if (doDfsCombinedRssi)
|
||||
rssi = (uint8_t) rxs->rs_rssi;
|
||||
else
|
||||
rssi = (uint8_t) rxs->rs_rssi_ctl[0];
|
||||
|
||||
/* Set this; but only use it if doDfsExtCh is set */
|
||||
ext_rssi = (uint8_t) rxs->rs_rssi_ext[0];
|
||||
|
||||
/* Cap it at 0 if the RSSI is a negative number */
|
||||
if (rssi & 0x80)
|
||||
rssi = 0;
|
||||
|
||||
if (ext_rssi & 0x80)
|
||||
ext_rssi = 0;
|
||||
|
||||
/*
|
||||
* Fetch the relevant data from the frame
|
||||
*/
|
||||
if (doDfsExtCh) {
|
||||
if (datalen < 3)
|
||||
return AH_FALSE;
|
||||
|
||||
/* Last three bytes of the frame are of interest */
|
||||
pulse_length_pri = *(buf + datalen - 3);
|
||||
pulse_length_ext = *(buf + datalen - 2);
|
||||
pulse_bw_info = *(buf + datalen - 1);
|
||||
HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, ext_rssi=%d, pulse_length_pri=%d,"
|
||||
" pulse_length_ext=%d, pulse_bw_info=%x\n",
|
||||
__func__, rssi, ext_rssi, pulse_length_pri, pulse_length_ext,
|
||||
pulse_bw_info);
|
||||
} else {
|
||||
/* The pulse width is byte 0 of the data */
|
||||
if (datalen >= 1)
|
||||
dur = ((uint8_t) buf[0]) & 0xff;
|
||||
else
|
||||
dur = 0;
|
||||
|
||||
if (dur == 0 && rssi == 0) {
|
||||
HALDEBUG(ah, HAL_DEBUG_DFS, "%s: dur and rssi are 0\n", __func__);
|
||||
return AH_FALSE;
|
||||
}
|
||||
|
||||
HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, dur=%d\n", __func__, rssi, dur);
|
||||
|
||||
/* Single-channel only */
|
||||
pri_found = 1;
|
||||
ext_found = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If doing extended channel data, pulse_bw_info must
|
||||
* have one of the flags set.
|
||||
*/
|
||||
if (doDfsExtCh && pulse_bw_info == 0x0)
|
||||
return AH_FALSE;
|
||||
|
||||
/*
|
||||
* If the extended channel data is available, calculate
|
||||
* which to pay attention to.
|
||||
*/
|
||||
if (doDfsExtCh) {
|
||||
/* If pulse is on DC, take the larger duration of the two */
|
||||
if ((pulse_bw_info & EXT_CH_RADAR_FOUND) &&
|
||||
(pulse_bw_info & PRI_CH_RADAR_FOUND)) {
|
||||
is_dc = 1;
|
||||
if (pulse_length_ext > pulse_length_pri) {
|
||||
dur = pulse_length_ext;
|
||||
pri_found = 0;
|
||||
ext_found = 1;
|
||||
} else {
|
||||
dur = pulse_length_pri;
|
||||
pri_found = 1;
|
||||
ext_found = 0;
|
||||
}
|
||||
} else if (pulse_bw_info & EXT_CH_RADAR_EARLY_FOUND) {
|
||||
dur = pulse_length_ext;
|
||||
pri_found = 0;
|
||||
ext_found = 1;
|
||||
early_ext = 1;
|
||||
} else if (pulse_bw_info & PRI_CH_RADAR_FOUND) {
|
||||
dur = pulse_length_pri;
|
||||
pri_found = 1;
|
||||
ext_found = 0;
|
||||
} else if (pulse_bw_info & EXT_CH_RADAR_FOUND) {
|
||||
dur = pulse_length_ext;
|
||||
pri_found = 0;
|
||||
ext_found = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* For enhanced DFS (Merlin and later), pulse_bw_info has
|
||||
* implications for selecting the correct RSSI value.
|
||||
*/
|
||||
if (doDfsEnhanced) {
|
||||
switch (pulse_bw_info & 0x03) {
|
||||
case 0:
|
||||
/* No radar? */
|
||||
rssi = 0;
|
||||
break;
|
||||
case PRI_CH_RADAR_FOUND:
|
||||
/* Radar in primary channel */
|
||||
/* Cannot use ctrl channel RSSI if ext channel is stronger */
|
||||
if (ext_rssi >= (rssi + 3)) {
|
||||
rssi = 0;
|
||||
};
|
||||
break;
|
||||
case EXT_CH_RADAR_FOUND:
|
||||
/* Radar in extended channel */
|
||||
/* Cannot use ext channel RSSI if ctrl channel is stronger */
|
||||
if (rssi >= (ext_rssi + 12)) {
|
||||
rssi = 0;
|
||||
} else {
|
||||
rssi = ext_rssi;
|
||||
}
|
||||
break;
|
||||
case (PRI_CH_RADAR_FOUND | EXT_CH_RADAR_FOUND):
|
||||
/* When both are present, use stronger one */
|
||||
if (rssi < ext_rssi)
|
||||
rssi = ext_rssi;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If not doing enhanced DFS, choose the ext channel if
|
||||
* it is stronger than the main channel
|
||||
*/
|
||||
if (doDfsExtCh && !doDfsEnhanced) {
|
||||
if ((ext_rssi > rssi) && (ext_rssi < 128))
|
||||
rssi = ext_rssi;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX what happens if the above code decides the RSSI
|
||||
* XXX wasn't valid, an sets it to 0?
|
||||
*/
|
||||
|
||||
/*
|
||||
* Fill out dfs_event structure.
|
||||
*/
|
||||
event->re_full_ts = fulltsf;
|
||||
event->re_ts = rxs->rs_tstamp;
|
||||
event->re_rssi = rssi;
|
||||
event->re_dur = dur;
|
||||
|
||||
event->re_flags = 0;
|
||||
if (pri_found)
|
||||
event->re_flags |= HAL_DFS_EVENT_PRICH;
|
||||
if (ext_found)
|
||||
event->re_flags |= HAL_DFS_EVENT_EXTCH;
|
||||
if (early_ext)
|
||||
event->re_flags |= HAL_DFS_EVENT_EXTEARLY;
|
||||
if (is_dc)
|
||||
event->re_flags |= HAL_DFS_EVENT_ISDC;
|
||||
|
||||
return AH_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return whether fast-clock is currently enabled for this
|
||||
* channel.
|
||||
*/
|
||||
HAL_BOOL
|
||||
ar5416IsFastClockEnabled(struct ath_hal *ah)
|
||||
{
|
||||
struct ath_hal_private *ahp = AH_PRIVATE(ah);
|
||||
|
||||
return IS_5GHZ_FAST_CLOCK_EN(ah, ahp->ah_curchan);
|
||||
}
|
||||
|
387
sys/dev/ath/ath_hal/ar5416/ar5416_radar.c
Normal file
387
sys/dev/ath/ath_hal/ar5416/ar5416_radar.c
Normal file
@ -0,0 +1,387 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011 Atheros Communications, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
#include "opt_ah.h"
|
||||
|
||||
#include "ah.h"
|
||||
#include "ah_internal.h"
|
||||
#include "ah_devid.h"
|
||||
#include "ah_desc.h" /* NB: for HAL_PHYERR* */
|
||||
|
||||
#include "ar5416/ar5416.h"
|
||||
#include "ar5416/ar5416reg.h"
|
||||
#include "ar5416/ar5416phy.h"
|
||||
|
||||
#include "ah_eeprom_v14.h" /* for owl_get_ntxchains() */
|
||||
|
||||
/*
|
||||
* Get the radar parameter values and return them in the pe
|
||||
* structure
|
||||
*/
|
||||
void
|
||||
ar5416GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
|
||||
{
|
||||
uint32_t val, temp;
|
||||
|
||||
val = OS_REG_READ(ah, AR_PHY_RADAR_0);
|
||||
|
||||
temp = MS(val,AR_PHY_RADAR_0_FIRPWR);
|
||||
temp |= 0xFFFFFF80;
|
||||
pe->pe_firpwr = temp;
|
||||
pe->pe_rrssi = MS(val, AR_PHY_RADAR_0_RRSSI);
|
||||
pe->pe_height = MS(val, AR_PHY_RADAR_0_HEIGHT);
|
||||
pe->pe_prssi = MS(val, AR_PHY_RADAR_0_PRSSI);
|
||||
pe->pe_inband = MS(val, AR_PHY_RADAR_0_INBAND);
|
||||
|
||||
/* RADAR_1 values */
|
||||
val = OS_REG_READ(ah, AR_PHY_RADAR_1);
|
||||
pe->pe_relpwr = MS(val, AR_PHY_RADAR_1_RELPWR_THRESH);
|
||||
pe->pe_relstep = MS(val, AR_PHY_RADAR_1_RELSTEP_THRESH);
|
||||
pe->pe_maxlen = MS(val, AR_PHY_RADAR_1_MAXLEN);
|
||||
|
||||
pe->pe_extchannel = !! (OS_REG_READ(ah, AR_PHY_RADAR_EXT) &
|
||||
AR_PHY_RADAR_EXT_ENA);
|
||||
|
||||
pe->pe_usefir128 = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
|
||||
AR_PHY_RADAR_1_USE_FIR128);
|
||||
pe->pe_blockradar = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
|
||||
AR_PHY_RADAR_1_BLOCK_CHECK);
|
||||
pe->pe_enmaxrssi = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
|
||||
AR_PHY_RADAR_1_MAX_RRSSI);
|
||||
pe->pe_enabled = !!
|
||||
(OS_REG_READ(ah, AR_PHY_RADAR_0) & AR_PHY_RADAR_0_ENA);
|
||||
pe->pe_enrelpwr = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
|
||||
AR_PHY_RADAR_1_RELPWR_ENA);
|
||||
pe->pe_en_relstep_check = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
|
||||
AR_PHY_RADAR_1_RELSTEP_CHECK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable radar detection and set the radar parameters per the
|
||||
* values in pe
|
||||
*/
|
||||
void
|
||||
ar5416EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = OS_REG_READ(ah, AR_PHY_RADAR_0);
|
||||
|
||||
if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) {
|
||||
val &= ~AR_PHY_RADAR_0_FIRPWR;
|
||||
val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR);
|
||||
}
|
||||
if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) {
|
||||
val &= ~AR_PHY_RADAR_0_RRSSI;
|
||||
val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI);
|
||||
}
|
||||
if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) {
|
||||
val &= ~AR_PHY_RADAR_0_HEIGHT;
|
||||
val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT);
|
||||
}
|
||||
if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) {
|
||||
val &= ~AR_PHY_RADAR_0_PRSSI;
|
||||
val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI);
|
||||
}
|
||||
if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) {
|
||||
val &= ~AR_PHY_RADAR_0_INBAND;
|
||||
val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND);
|
||||
}
|
||||
|
||||
/*Enable FFT data*/
|
||||
val |= AR_PHY_RADAR_0_FFT_ENA;
|
||||
OS_REG_WRITE(ah, AR_PHY_RADAR_0, val);
|
||||
|
||||
/* Implicitly enable */
|
||||
if (pe->pe_enabled == 1)
|
||||
OS_REG_SET_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA);
|
||||
else if (pe->pe_enabled == 0)
|
||||
OS_REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA);
|
||||
|
||||
if (pe->pe_usefir128 == 1)
|
||||
OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_USE_FIR128);
|
||||
else if (pe->pe_usefir128 == 0)
|
||||
OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_USE_FIR128);
|
||||
|
||||
if (pe->pe_enmaxrssi == 1)
|
||||
OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_MAX_RRSSI);
|
||||
else if (pe->pe_enmaxrssi == 0)
|
||||
OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_MAX_RRSSI);
|
||||
|
||||
if (pe->pe_blockradar == 1)
|
||||
OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_BLOCK_CHECK);
|
||||
else if (pe->pe_blockradar == 0)
|
||||
OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_BLOCK_CHECK);
|
||||
|
||||
if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL) {
|
||||
val = OS_REG_READ(ah, AR_PHY_RADAR_1);
|
||||
val &= ~AR_PHY_RADAR_1_RELSTEP_THRESH;
|
||||
val |= SM(pe->pe_relstep, AR_PHY_RADAR_1_RELSTEP_THRESH);
|
||||
OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);
|
||||
}
|
||||
if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL) {
|
||||
val = OS_REG_READ(ah, AR_PHY_RADAR_1);
|
||||
val &= ~AR_PHY_RADAR_1_RELPWR_THRESH;
|
||||
val |= SM(pe->pe_relpwr, AR_PHY_RADAR_1_RELPWR_THRESH);
|
||||
OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);
|
||||
}
|
||||
|
||||
if (pe->pe_en_relstep_check == 1)
|
||||
OS_REG_SET_BIT(ah, AR_PHY_RADAR_1,
|
||||
AR_PHY_RADAR_1_RELSTEP_CHECK);
|
||||
else if (pe->pe_en_relstep_check == 0)
|
||||
OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1,
|
||||
AR_PHY_RADAR_1_RELSTEP_CHECK);
|
||||
|
||||
if (pe->pe_enrelpwr == 1)
|
||||
OS_REG_SET_BIT(ah, AR_PHY_RADAR_1,
|
||||
AR_PHY_RADAR_1_RELPWR_ENA);
|
||||
else if (pe->pe_enrelpwr == 0)
|
||||
OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1,
|
||||
AR_PHY_RADAR_1_RELPWR_ENA);
|
||||
|
||||
if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL) {
|
||||
val = OS_REG_READ(ah, AR_PHY_RADAR_1);
|
||||
val &= ~AR_PHY_RADAR_1_MAXLEN;
|
||||
val |= SM(pe->pe_maxlen, AR_PHY_RADAR_1_MAXLEN);
|
||||
OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable HT/40 if the upper layer asks;
|
||||
* it should check the channel is HT/40 and HAL_CAP_EXT_CHAN_DFS
|
||||
* is available.
|
||||
*/
|
||||
if (pe->pe_extchannel == 1)
|
||||
OS_REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
|
||||
else if (pe->pe_extchannel == 0)
|
||||
OS_REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract the radar event information from the given phy error.
|
||||
*
|
||||
* Returns AH_TRUE if the phy error was actually a phy error,
|
||||
* AH_FALSE if the phy error wasn't a phy error.
|
||||
*/
|
||||
|
||||
/* Flags for pulse_bw_info */
|
||||
#define PRI_CH_RADAR_FOUND 0x01
|
||||
#define EXT_CH_RADAR_FOUND 0x02
|
||||
#define EXT_CH_RADAR_EARLY_FOUND 0x04
|
||||
|
||||
HAL_BOOL
|
||||
ar5416ProcessRadarEvent(struct ath_hal *ah, struct ath_rx_status *rxs,
|
||||
uint64_t fulltsf, const char *buf, HAL_DFS_EVENT *event)
|
||||
{
|
||||
HAL_BOOL doDfsExtCh;
|
||||
HAL_BOOL doDfsEnhanced;
|
||||
HAL_BOOL doDfsCombinedRssi;
|
||||
|
||||
uint8_t rssi = 0, ext_rssi = 0;
|
||||
uint8_t pulse_bw_info = 0, pulse_length_ext = 0, pulse_length_pri = 0;
|
||||
uint32_t dur = 0;
|
||||
int pri_found = 1, ext_found = 0;
|
||||
int early_ext = 0;
|
||||
int is_dc = 0;
|
||||
uint16_t datalen; /* length from the RX status field */
|
||||
|
||||
/* Check whether the given phy error is a radar event */
|
||||
if ((rxs->rs_phyerr != HAL_PHYERR_RADAR) &&
|
||||
(rxs->rs_phyerr != HAL_PHYERR_FALSE_RADAR_EXT)) {
|
||||
return AH_FALSE;
|
||||
}
|
||||
|
||||
/* Grab copies of the capabilities; just to make the code clearer */
|
||||
doDfsExtCh = AH_PRIVATE(ah)->ah_caps.halExtChanDfsSupport;
|
||||
doDfsEnhanced = AH_PRIVATE(ah)->ah_caps.halEnhancedDfsSupport;
|
||||
doDfsCombinedRssi = AH_PRIVATE(ah)->ah_caps.halUseCombinedRadarRssi;
|
||||
|
||||
datalen = rxs->rs_datalen;
|
||||
|
||||
/* If hardware supports it, use combined RSSI, else use chain 0 RSSI */
|
||||
if (doDfsCombinedRssi)
|
||||
rssi = (uint8_t) rxs->rs_rssi;
|
||||
else
|
||||
rssi = (uint8_t) rxs->rs_rssi_ctl[0];
|
||||
|
||||
/* Set this; but only use it if doDfsExtCh is set */
|
||||
ext_rssi = (uint8_t) rxs->rs_rssi_ext[0];
|
||||
|
||||
/* Cap it at 0 if the RSSI is a negative number */
|
||||
if (rssi & 0x80)
|
||||
rssi = 0;
|
||||
|
||||
if (ext_rssi & 0x80)
|
||||
ext_rssi = 0;
|
||||
|
||||
/*
|
||||
* Fetch the relevant data from the frame
|
||||
*/
|
||||
if (doDfsExtCh) {
|
||||
if (datalen < 3)
|
||||
return AH_FALSE;
|
||||
|
||||
/* Last three bytes of the frame are of interest */
|
||||
pulse_length_pri = *(buf + datalen - 3);
|
||||
pulse_length_ext = *(buf + datalen - 2);
|
||||
pulse_bw_info = *(buf + datalen - 1);
|
||||
HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, ext_rssi=%d, pulse_length_pri=%d,"
|
||||
" pulse_length_ext=%d, pulse_bw_info=%x\n",
|
||||
__func__, rssi, ext_rssi, pulse_length_pri, pulse_length_ext,
|
||||
pulse_bw_info);
|
||||
} else {
|
||||
/* The pulse width is byte 0 of the data */
|
||||
if (datalen >= 1)
|
||||
dur = ((uint8_t) buf[0]) & 0xff;
|
||||
else
|
||||
dur = 0;
|
||||
|
||||
if (dur == 0 && rssi == 0) {
|
||||
HALDEBUG(ah, HAL_DEBUG_DFS, "%s: dur and rssi are 0\n", __func__);
|
||||
return AH_FALSE;
|
||||
}
|
||||
|
||||
HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, dur=%d\n", __func__, rssi, dur);
|
||||
|
||||
/* Single-channel only */
|
||||
pri_found = 1;
|
||||
ext_found = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If doing extended channel data, pulse_bw_info must
|
||||
* have one of the flags set.
|
||||
*/
|
||||
if (doDfsExtCh && pulse_bw_info == 0x0)
|
||||
return AH_FALSE;
|
||||
|
||||
/*
|
||||
* If the extended channel data is available, calculate
|
||||
* which to pay attention to.
|
||||
*/
|
||||
if (doDfsExtCh) {
|
||||
/* If pulse is on DC, take the larger duration of the two */
|
||||
if ((pulse_bw_info & EXT_CH_RADAR_FOUND) &&
|
||||
(pulse_bw_info & PRI_CH_RADAR_FOUND)) {
|
||||
is_dc = 1;
|
||||
if (pulse_length_ext > pulse_length_pri) {
|
||||
dur = pulse_length_ext;
|
||||
pri_found = 0;
|
||||
ext_found = 1;
|
||||
} else {
|
||||
dur = pulse_length_pri;
|
||||
pri_found = 1;
|
||||
ext_found = 0;
|
||||
}
|
||||
} else if (pulse_bw_info & EXT_CH_RADAR_EARLY_FOUND) {
|
||||
dur = pulse_length_ext;
|
||||
pri_found = 0;
|
||||
ext_found = 1;
|
||||
early_ext = 1;
|
||||
} else if (pulse_bw_info & PRI_CH_RADAR_FOUND) {
|
||||
dur = pulse_length_pri;
|
||||
pri_found = 1;
|
||||
ext_found = 0;
|
||||
} else if (pulse_bw_info & EXT_CH_RADAR_FOUND) {
|
||||
dur = pulse_length_ext;
|
||||
pri_found = 0;
|
||||
ext_found = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* For enhanced DFS (Merlin and later), pulse_bw_info has
|
||||
* implications for selecting the correct RSSI value.
|
||||
*/
|
||||
if (doDfsEnhanced) {
|
||||
switch (pulse_bw_info & 0x03) {
|
||||
case 0:
|
||||
/* No radar? */
|
||||
rssi = 0;
|
||||
break;
|
||||
case PRI_CH_RADAR_FOUND:
|
||||
/* Radar in primary channel */
|
||||
/* Cannot use ctrl channel RSSI if ext channel is stronger */
|
||||
if (ext_rssi >= (rssi + 3)) {
|
||||
rssi = 0;
|
||||
};
|
||||
break;
|
||||
case EXT_CH_RADAR_FOUND:
|
||||
/* Radar in extended channel */
|
||||
/* Cannot use ext channel RSSI if ctrl channel is stronger */
|
||||
if (rssi >= (ext_rssi + 12)) {
|
||||
rssi = 0;
|
||||
} else {
|
||||
rssi = ext_rssi;
|
||||
}
|
||||
break;
|
||||
case (PRI_CH_RADAR_FOUND | EXT_CH_RADAR_FOUND):
|
||||
/* When both are present, use stronger one */
|
||||
if (rssi < ext_rssi)
|
||||
rssi = ext_rssi;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If not doing enhanced DFS, choose the ext channel if
|
||||
* it is stronger than the main channel
|
||||
*/
|
||||
if (doDfsExtCh && !doDfsEnhanced) {
|
||||
if ((ext_rssi > rssi) && (ext_rssi < 128))
|
||||
rssi = ext_rssi;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX what happens if the above code decides the RSSI
|
||||
* XXX wasn't valid, an sets it to 0?
|
||||
*/
|
||||
|
||||
/*
|
||||
* Fill out dfs_event structure.
|
||||
*/
|
||||
event->re_full_ts = fulltsf;
|
||||
event->re_ts = rxs->rs_tstamp;
|
||||
event->re_rssi = rssi;
|
||||
event->re_dur = dur;
|
||||
|
||||
event->re_flags = 0;
|
||||
if (pri_found)
|
||||
event->re_flags |= HAL_DFS_EVENT_PRICH;
|
||||
if (ext_found)
|
||||
event->re_flags |= HAL_DFS_EVENT_EXTCH;
|
||||
if (early_ext)
|
||||
event->re_flags |= HAL_DFS_EVENT_EXTEARLY;
|
||||
if (is_dc)
|
||||
event->re_flags |= HAL_DFS_EVENT_ISDC;
|
||||
|
||||
return AH_TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return whether fast-clock is currently enabled for this
|
||||
* channel.
|
||||
*/
|
||||
HAL_BOOL
|
||||
ar5416IsFastClockEnabled(struct ath_hal *ah)
|
||||
{
|
||||
struct ath_hal_private *ahp = AH_PRIVATE(ah);
|
||||
|
||||
return IS_5GHZ_FAST_CLOCK_EN(ah, ahp->ah_curchan);
|
||||
}
|
@ -88,8 +88,8 @@ SRCS+= ah_eeprom_v14.c ah_eeprom_v4k.c \
|
||||
ar5416_ani.c ar5416_attach.c ar5416_beacon.c ar5416_cal.c \
|
||||
ar5416_cal_iq.c ar5416_cal_adcgain.c ar5416_cal_adcdc.c \
|
||||
ar5416_eeprom.c ar5416_gpio.c ar5416_interrupts.c ar5416_keycache.c \
|
||||
ar5416_misc.c ar5416_phy.c ar5416_power.c ar5416_recv.c \
|
||||
ar5416_reset.c ar5416_xmit.c
|
||||
ar5416_misc.c ar5416_phy.c ar5416_power.c ar5416_radar.c \
|
||||
ar5416_recv.c ar5416_reset.c ar5416_xmit.c
|
||||
|
||||
# RF backend for 5416, 9130 and 9160
|
||||
SRCS+= ar2133.c
|
||||
|
Loading…
Reference in New Issue
Block a user