1231927Sadrian/*
2231927Sadrian * Copyright (c) 2010-2011 Atheros Communications, Inc.
3231927Sadrian *
4231927Sadrian * Permission to use, copy, modify, and/or distribute this software for any
5231927Sadrian * purpose with or without fee is hereby granted, provided that the above
6231927Sadrian * copyright notice and this permission notice appear in all copies.
7231927Sadrian *
8231927Sadrian * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9231927Sadrian * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10231927Sadrian * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11231927Sadrian * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12231927Sadrian * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13231927Sadrian * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14231927Sadrian * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15231927Sadrian *
16231927Sadrian * $FreeBSD$
17231927Sadrian */
18231927Sadrian#include "opt_ah.h"
19231927Sadrian
20231927Sadrian#include "ah.h"
21231927Sadrian#include "ah_internal.h"
22231927Sadrian#include "ah_devid.h"
23231927Sadrian#include "ah_desc.h"                    /* NB: for HAL_PHYERR* */
24231927Sadrian
25231927Sadrian#include "ar5416/ar5416.h"
26231927Sadrian#include "ar5416/ar5416reg.h"
27231927Sadrian#include "ar5416/ar5416phy.h"
28231927Sadrian
29231927Sadrian#include "ah_eeprom_v14.h"	/* for owl_get_ntxchains() */
30231927Sadrian
31231927Sadrian/*
32239638Sadrian * These are default parameters for the AR5416 and
33239638Sadrian * later 802.11n NICs.  They simply enable some
34239638Sadrian * radar pulse event generation.
35239638Sadrian *
36239638Sadrian * These are very likely not valid for the AR5212 era
37239638Sadrian * NICs.
38239638Sadrian *
39239638Sadrian * Since these define signal sizing and threshold
40239638Sadrian * parameters, they may need changing based on the
41239638Sadrian * specific antenna and receive amplifier
42239638Sadrian * configuration.
43239638Sadrian */
44239638Sadrian#define	AR5416_DFS_FIRPWR	-33
45239638Sadrian#define	AR5416_DFS_RRSSI	20
46239638Sadrian#define	AR5416_DFS_HEIGHT	10
47239638Sadrian#define	AR5416_DFS_PRSSI	15
48239638Sadrian#define	AR5416_DFS_INBAND	15
49239638Sadrian#define	AR5416_DFS_RELPWR	8
50239638Sadrian#define	AR5416_DFS_RELSTEP	12
51239638Sadrian#define	AR5416_DFS_MAXLEN	255
52239638Sadrian
53239638SadrianHAL_BOOL
54239638Sadrianar5416GetDfsDefaultThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
55239638Sadrian{
56239638Sadrian
57239638Sadrian	/*
58239638Sadrian	 * These are general examples of the parameter values
59239638Sadrian	 * to use when configuring radar pulse detection for
60239638Sadrian	 * the AR5416, AR91xx, AR92xx NICs.  They are only
61239638Sadrian	 * for testing and do require tuning depending upon the
62239638Sadrian	 * hardware and deployment specifics.
63239638Sadrian	 */
64239638Sadrian	pe->pe_firpwr = AR5416_DFS_FIRPWR;
65239638Sadrian	pe->pe_rrssi = AR5416_DFS_RRSSI;
66239638Sadrian	pe->pe_height = AR5416_DFS_HEIGHT;
67239638Sadrian	pe->pe_prssi = AR5416_DFS_PRSSI;
68239638Sadrian	pe->pe_inband = AR5416_DFS_INBAND;
69239638Sadrian	pe->pe_relpwr = AR5416_DFS_RELPWR;
70239638Sadrian	pe->pe_relstep = AR5416_DFS_RELSTEP;
71239638Sadrian	pe->pe_maxlen = AR5416_DFS_MAXLEN;
72239638Sadrian
73239638Sadrian	return (AH_TRUE);
74239638Sadrian}
75239638Sadrian
76239638Sadrian/*
77231927Sadrian * Get the radar parameter values and return them in the pe
78231927Sadrian * structure
79231927Sadrian */
80231927Sadrianvoid
81231927Sadrianar5416GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
82231927Sadrian{
83231927Sadrian	uint32_t val, temp;
84231927Sadrian
85231927Sadrian	val = OS_REG_READ(ah, AR_PHY_RADAR_0);
86231927Sadrian
87231927Sadrian	temp = MS(val,AR_PHY_RADAR_0_FIRPWR);
88231927Sadrian	temp |= 0xFFFFFF80;
89231927Sadrian	pe->pe_firpwr = temp;
90231927Sadrian	pe->pe_rrssi = MS(val, AR_PHY_RADAR_0_RRSSI);
91231927Sadrian	pe->pe_height =  MS(val, AR_PHY_RADAR_0_HEIGHT);
92231927Sadrian	pe->pe_prssi = MS(val, AR_PHY_RADAR_0_PRSSI);
93231927Sadrian	pe->pe_inband = MS(val, AR_PHY_RADAR_0_INBAND);
94231927Sadrian
95231927Sadrian	/* RADAR_1 values */
96231927Sadrian	val = OS_REG_READ(ah, AR_PHY_RADAR_1);
97231927Sadrian	pe->pe_relpwr = MS(val, AR_PHY_RADAR_1_RELPWR_THRESH);
98231927Sadrian	pe->pe_relstep = MS(val, AR_PHY_RADAR_1_RELSTEP_THRESH);
99231927Sadrian	pe->pe_maxlen = MS(val, AR_PHY_RADAR_1_MAXLEN);
100231927Sadrian
101231927Sadrian	pe->pe_extchannel = !! (OS_REG_READ(ah, AR_PHY_RADAR_EXT) &
102231927Sadrian	    AR_PHY_RADAR_EXT_ENA);
103231927Sadrian
104231927Sadrian	pe->pe_usefir128 = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
105231927Sadrian	    AR_PHY_RADAR_1_USE_FIR128);
106231927Sadrian	pe->pe_blockradar = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
107231927Sadrian	    AR_PHY_RADAR_1_BLOCK_CHECK);
108231927Sadrian	pe->pe_enmaxrssi = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
109231927Sadrian	    AR_PHY_RADAR_1_MAX_RRSSI);
110231927Sadrian	pe->pe_enabled = !!
111231927Sadrian	    (OS_REG_READ(ah, AR_PHY_RADAR_0) & AR_PHY_RADAR_0_ENA);
112231927Sadrian	pe->pe_enrelpwr = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
113231927Sadrian	    AR_PHY_RADAR_1_RELPWR_ENA);
114231927Sadrian	pe->pe_en_relstep_check = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
115231927Sadrian	    AR_PHY_RADAR_1_RELSTEP_CHECK);
116231927Sadrian}
117231927Sadrian
118231927Sadrian/*
119231927Sadrian * Enable radar detection and set the radar parameters per the
120231927Sadrian * values in pe
121231927Sadrian */
122231927Sadrianvoid
123231927Sadrianar5416EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
124231927Sadrian{
125231927Sadrian	uint32_t val;
126231927Sadrian
127231927Sadrian	val = OS_REG_READ(ah, AR_PHY_RADAR_0);
128231927Sadrian
129231927Sadrian	if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) {
130231927Sadrian		val &= ~AR_PHY_RADAR_0_FIRPWR;
131231927Sadrian		val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR);
132231927Sadrian	}
133231927Sadrian	if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) {
134231927Sadrian		val &= ~AR_PHY_RADAR_0_RRSSI;
135231927Sadrian		val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI);
136231927Sadrian	}
137231927Sadrian	if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) {
138231927Sadrian		val &= ~AR_PHY_RADAR_0_HEIGHT;
139231927Sadrian		val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT);
140231927Sadrian	}
141231927Sadrian	if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) {
142231927Sadrian		val &= ~AR_PHY_RADAR_0_PRSSI;
143231927Sadrian		val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI);
144231927Sadrian	}
145231927Sadrian	if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) {
146231927Sadrian		val &= ~AR_PHY_RADAR_0_INBAND;
147231927Sadrian		val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND);
148231927Sadrian	}
149231927Sadrian
150231927Sadrian	/*Enable FFT data*/
151231927Sadrian	val |= AR_PHY_RADAR_0_FFT_ENA;
152231927Sadrian	OS_REG_WRITE(ah, AR_PHY_RADAR_0, val);
153231927Sadrian
154231927Sadrian	/* Implicitly enable */
155231927Sadrian	if (pe->pe_enabled == 1)
156231927Sadrian		OS_REG_SET_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA);
157231927Sadrian	else if (pe->pe_enabled == 0)
158231927Sadrian		OS_REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA);
159231927Sadrian
160231927Sadrian	if (pe->pe_usefir128 == 1)
161231927Sadrian		OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_USE_FIR128);
162231927Sadrian	else if (pe->pe_usefir128 == 0)
163231927Sadrian		OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_USE_FIR128);
164231927Sadrian
165231927Sadrian	if (pe->pe_enmaxrssi == 1)
166231927Sadrian		OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_MAX_RRSSI);
167231927Sadrian	else if (pe->pe_enmaxrssi == 0)
168231927Sadrian		OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_MAX_RRSSI);
169231927Sadrian
170231927Sadrian	if (pe->pe_blockradar == 1)
171231927Sadrian		OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_BLOCK_CHECK);
172231927Sadrian	else if (pe->pe_blockradar == 0)
173231927Sadrian		OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_BLOCK_CHECK);
174231927Sadrian
175231927Sadrian	if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL) {
176231927Sadrian		val = OS_REG_READ(ah, AR_PHY_RADAR_1);
177231927Sadrian		val &= ~AR_PHY_RADAR_1_RELSTEP_THRESH;
178231927Sadrian		val |= SM(pe->pe_relstep, AR_PHY_RADAR_1_RELSTEP_THRESH);
179231927Sadrian		OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);
180231927Sadrian	}
181231927Sadrian	if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL) {
182231927Sadrian		val = OS_REG_READ(ah, AR_PHY_RADAR_1);
183231927Sadrian		val &= ~AR_PHY_RADAR_1_RELPWR_THRESH;
184231927Sadrian		val |= SM(pe->pe_relpwr, AR_PHY_RADAR_1_RELPWR_THRESH);
185231927Sadrian		OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);
186231927Sadrian	}
187231927Sadrian
188231927Sadrian	if (pe->pe_en_relstep_check == 1)
189231927Sadrian		OS_REG_SET_BIT(ah, AR_PHY_RADAR_1,
190231927Sadrian		    AR_PHY_RADAR_1_RELSTEP_CHECK);
191231927Sadrian	else if (pe->pe_en_relstep_check == 0)
192231927Sadrian		OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1,
193231927Sadrian		    AR_PHY_RADAR_1_RELSTEP_CHECK);
194231927Sadrian
195231927Sadrian	if (pe->pe_enrelpwr == 1)
196231927Sadrian		OS_REG_SET_BIT(ah, AR_PHY_RADAR_1,
197231927Sadrian		    AR_PHY_RADAR_1_RELPWR_ENA);
198231927Sadrian	else if (pe->pe_enrelpwr == 0)
199231927Sadrian		OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1,
200231927Sadrian		    AR_PHY_RADAR_1_RELPWR_ENA);
201231927Sadrian
202231927Sadrian	if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL) {
203231927Sadrian		val = OS_REG_READ(ah, AR_PHY_RADAR_1);
204231927Sadrian		val &= ~AR_PHY_RADAR_1_MAXLEN;
205231927Sadrian		val |= SM(pe->pe_maxlen, AR_PHY_RADAR_1_MAXLEN);
206231927Sadrian		OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);
207231927Sadrian	}
208231927Sadrian
209231927Sadrian	/*
210231927Sadrian	 * Enable HT/40 if the upper layer asks;
211231927Sadrian	 * it should check the channel is HT/40 and HAL_CAP_EXT_CHAN_DFS
212231927Sadrian	 * is available.
213231927Sadrian	 */
214231927Sadrian	if (pe->pe_extchannel == 1)
215231927Sadrian		OS_REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
216231927Sadrian	else if (pe->pe_extchannel == 0)
217231927Sadrian		OS_REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
218231927Sadrian}
219231927Sadrian
220231927Sadrian/*
221231927Sadrian * Extract the radar event information from the given phy error.
222231927Sadrian *
223231927Sadrian * Returns AH_TRUE if the phy error was actually a phy error,
224231927Sadrian * AH_FALSE if the phy error wasn't a phy error.
225231927Sadrian */
226231927Sadrian
227231927Sadrian/* Flags for pulse_bw_info */
228231927Sadrian#define	PRI_CH_RADAR_FOUND		0x01
229231927Sadrian#define	EXT_CH_RADAR_FOUND		0x02
230231927Sadrian#define	EXT_CH_RADAR_EARLY_FOUND	0x04
231231927Sadrian
232231927SadrianHAL_BOOL
233231927Sadrianar5416ProcessRadarEvent(struct ath_hal *ah, struct ath_rx_status *rxs,
234231927Sadrian    uint64_t fulltsf, const char *buf, HAL_DFS_EVENT *event)
235231927Sadrian{
236231927Sadrian	HAL_BOOL doDfsExtCh;
237231927Sadrian	HAL_BOOL doDfsEnhanced;
238231927Sadrian	HAL_BOOL doDfsCombinedRssi;
239231927Sadrian
240231927Sadrian	uint8_t rssi = 0, ext_rssi = 0;
241231927Sadrian	uint8_t pulse_bw_info = 0, pulse_length_ext = 0, pulse_length_pri = 0;
242231927Sadrian	uint32_t dur = 0;
243231927Sadrian	int pri_found = 1, ext_found = 0;
244231927Sadrian	int early_ext = 0;
245231927Sadrian	int is_dc = 0;
246231927Sadrian	uint16_t datalen;		/* length from the RX status field */
247231927Sadrian
248231927Sadrian	/* Check whether the given phy error is a radar event */
249231927Sadrian	if ((rxs->rs_phyerr != HAL_PHYERR_RADAR) &&
250231927Sadrian	    (rxs->rs_phyerr != HAL_PHYERR_FALSE_RADAR_EXT)) {
251231927Sadrian		return AH_FALSE;
252231927Sadrian	}
253231927Sadrian
254231927Sadrian	/* Grab copies of the capabilities; just to make the code clearer */
255231927Sadrian	doDfsExtCh = AH_PRIVATE(ah)->ah_caps.halExtChanDfsSupport;
256231927Sadrian	doDfsEnhanced = AH_PRIVATE(ah)->ah_caps.halEnhancedDfsSupport;
257231927Sadrian	doDfsCombinedRssi = AH_PRIVATE(ah)->ah_caps.halUseCombinedRadarRssi;
258231927Sadrian
259231927Sadrian	datalen = rxs->rs_datalen;
260231927Sadrian
261231927Sadrian	/* If hardware supports it, use combined RSSI, else use chain 0 RSSI */
262231927Sadrian	if (doDfsCombinedRssi)
263231927Sadrian		rssi = (uint8_t) rxs->rs_rssi;
264231927Sadrian	else
265231927Sadrian		rssi = (uint8_t) rxs->rs_rssi_ctl[0];
266231927Sadrian
267231927Sadrian	/* Set this; but only use it if doDfsExtCh is set */
268231927Sadrian	ext_rssi = (uint8_t) rxs->rs_rssi_ext[0];
269231927Sadrian
270231927Sadrian	/* Cap it at 0 if the RSSI is a negative number */
271231927Sadrian	if (rssi & 0x80)
272231927Sadrian		rssi = 0;
273231927Sadrian
274231927Sadrian	if (ext_rssi & 0x80)
275231927Sadrian		ext_rssi = 0;
276231927Sadrian
277231927Sadrian	/*
278231927Sadrian	 * Fetch the relevant data from the frame
279231927Sadrian	 */
280231927Sadrian	if (doDfsExtCh) {
281231927Sadrian		if (datalen < 3)
282231927Sadrian			return AH_FALSE;
283231927Sadrian
284231927Sadrian		/* Last three bytes of the frame are of interest */
285231927Sadrian		pulse_length_pri = *(buf + datalen - 3);
286231927Sadrian		pulse_length_ext = *(buf + datalen - 2);
287231927Sadrian		pulse_bw_info = *(buf + datalen - 1);
288231927Sadrian		HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, ext_rssi=%d, pulse_length_pri=%d,"
289231927Sadrian		    " pulse_length_ext=%d, pulse_bw_info=%x\n",
290231927Sadrian		    __func__, rssi, ext_rssi, pulse_length_pri, pulse_length_ext,
291231927Sadrian		    pulse_bw_info);
292231927Sadrian	} else {
293231927Sadrian		/* The pulse width is byte 0 of the data */
294231927Sadrian		if (datalen >= 1)
295231927Sadrian			dur = ((uint8_t) buf[0]) & 0xff;
296231927Sadrian		else
297231927Sadrian			dur = 0;
298231927Sadrian
299231927Sadrian		if (dur == 0 && rssi == 0) {
300231927Sadrian			HALDEBUG(ah, HAL_DEBUG_DFS, "%s: dur and rssi are 0\n", __func__);
301231927Sadrian			return AH_FALSE;
302231927Sadrian		}
303231927Sadrian
304231927Sadrian		HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, dur=%d\n", __func__, rssi, dur);
305231927Sadrian
306231927Sadrian		/* Single-channel only */
307231927Sadrian		pri_found = 1;
308231927Sadrian		ext_found = 0;
309231927Sadrian	}
310231927Sadrian
311231927Sadrian	/*
312231927Sadrian	 * If doing extended channel data, pulse_bw_info must
313231927Sadrian	 * have one of the flags set.
314231927Sadrian	 */
315231927Sadrian	if (doDfsExtCh && pulse_bw_info == 0x0)
316231927Sadrian		return AH_FALSE;
317231927Sadrian
318231927Sadrian	/*
319231927Sadrian	 * If the extended channel data is available, calculate
320231927Sadrian	 * which to pay attention to.
321231927Sadrian	 */
322231927Sadrian	if (doDfsExtCh) {
323231927Sadrian		/* If pulse is on DC, take the larger duration of the two */
324231927Sadrian		if ((pulse_bw_info & EXT_CH_RADAR_FOUND) &&
325231927Sadrian		    (pulse_bw_info & PRI_CH_RADAR_FOUND)) {
326231927Sadrian			is_dc = 1;
327231927Sadrian			if (pulse_length_ext > pulse_length_pri) {
328231927Sadrian				dur = pulse_length_ext;
329231927Sadrian				pri_found = 0;
330231927Sadrian				ext_found = 1;
331231927Sadrian			} else {
332231927Sadrian				dur = pulse_length_pri;
333231927Sadrian				pri_found = 1;
334231927Sadrian				ext_found = 0;
335231927Sadrian			}
336231927Sadrian		} else if (pulse_bw_info & EXT_CH_RADAR_EARLY_FOUND) {
337231927Sadrian			dur = pulse_length_ext;
338231927Sadrian			pri_found = 0;
339231927Sadrian			ext_found = 1;
340231927Sadrian			early_ext = 1;
341231927Sadrian		} else if (pulse_bw_info & PRI_CH_RADAR_FOUND) {
342231927Sadrian			dur = pulse_length_pri;
343231927Sadrian			pri_found = 1;
344231927Sadrian			ext_found = 0;
345231927Sadrian		} else if (pulse_bw_info & EXT_CH_RADAR_FOUND) {
346231927Sadrian			dur = pulse_length_ext;
347231927Sadrian			pri_found = 0;
348231927Sadrian			ext_found = 1;
349231927Sadrian		}
350231927Sadrian
351231927Sadrian	}
352231927Sadrian
353231927Sadrian	/*
354231927Sadrian	 * For enhanced DFS (Merlin and later), pulse_bw_info has
355231927Sadrian	 * implications for selecting the correct RSSI value.
356231927Sadrian	 */
357231927Sadrian	if (doDfsEnhanced) {
358231927Sadrian		switch (pulse_bw_info & 0x03) {
359231927Sadrian		case 0:
360231927Sadrian			/* No radar? */
361231927Sadrian			rssi = 0;
362231927Sadrian			break;
363231927Sadrian		case PRI_CH_RADAR_FOUND:
364231927Sadrian			/* Radar in primary channel */
365231927Sadrian			/* Cannot use ctrl channel RSSI if ext channel is stronger */
366231927Sadrian			if (ext_rssi >= (rssi + 3)) {
367231927Sadrian				rssi = 0;
368297793Spfg			}
369231927Sadrian			break;
370231927Sadrian		case EXT_CH_RADAR_FOUND:
371231927Sadrian			/* Radar in extended channel */
372231927Sadrian			/* Cannot use ext channel RSSI if ctrl channel is stronger */
373231927Sadrian			if (rssi >= (ext_rssi + 12)) {
374231927Sadrian				rssi = 0;
375231927Sadrian			} else {
376231927Sadrian				rssi = ext_rssi;
377231927Sadrian			}
378231927Sadrian			break;
379231927Sadrian		case (PRI_CH_RADAR_FOUND | EXT_CH_RADAR_FOUND):
380231927Sadrian			/* When both are present, use stronger one */
381231927Sadrian			if (rssi < ext_rssi)
382231927Sadrian				rssi = ext_rssi;
383231927Sadrian			break;
384231927Sadrian		}
385231927Sadrian	}
386231927Sadrian
387231927Sadrian	/*
388231927Sadrian	 * If not doing enhanced DFS, choose the ext channel if
389231927Sadrian	 * it is stronger than the main channel
390231927Sadrian	 */
391231927Sadrian	if (doDfsExtCh && !doDfsEnhanced) {
392231927Sadrian		if ((ext_rssi > rssi) && (ext_rssi < 128))
393231927Sadrian			rssi = ext_rssi;
394231927Sadrian	}
395231927Sadrian
396231927Sadrian	/*
397231927Sadrian	 * XXX what happens if the above code decides the RSSI
398231927Sadrian	 * XXX wasn't valid, an sets it to 0?
399231927Sadrian	 */
400231927Sadrian
401231927Sadrian	/*
402231927Sadrian	 * Fill out dfs_event structure.
403231927Sadrian	 */
404231927Sadrian	event->re_full_ts = fulltsf;
405231927Sadrian	event->re_ts = rxs->rs_tstamp;
406231927Sadrian	event->re_rssi = rssi;
407231927Sadrian	event->re_dur = dur;
408231927Sadrian
409231927Sadrian	event->re_flags = 0;
410231927Sadrian	if (pri_found)
411231927Sadrian		event->re_flags |= HAL_DFS_EVENT_PRICH;
412231927Sadrian	if (ext_found)
413231927Sadrian		event->re_flags |= HAL_DFS_EVENT_EXTCH;
414231927Sadrian	if (early_ext)
415231927Sadrian		event->re_flags |= HAL_DFS_EVENT_EXTEARLY;
416231927Sadrian	if (is_dc)
417231927Sadrian		event->re_flags |= HAL_DFS_EVENT_ISDC;
418231927Sadrian
419231927Sadrian	return AH_TRUE;
420231927Sadrian}
421231927Sadrian
422231927Sadrian/*
423231927Sadrian * Return whether fast-clock is currently enabled for this
424231927Sadrian * channel.
425231927Sadrian */
426231927SadrianHAL_BOOL
427231927Sadrianar5416IsFastClockEnabled(struct ath_hal *ah)
428231927Sadrian{
429231927Sadrian	struct ath_hal_private *ahp = AH_PRIVATE(ah);
430231927Sadrian
431231927Sadrian	return IS_5GHZ_FAST_CLOCK_EN(ah, ahp->ah_curchan);
432231927Sadrian}
433