ar5416_misc.c revision 231864
1/*
2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
3 * Copyright (c) 2002-2008 Atheros Communications, Inc.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 *
17 * $FreeBSD: head/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c 231864 2012-02-17 08:45:08Z adrian $
18 */
19#include "opt_ah.h"
20
21#include "ah.h"
22#include "ah_internal.h"
23#include "ah_devid.h"
24#include "ah_desc.h"                    /* NB: for HAL_PHYERR* */
25
26#include "ar5416/ar5416.h"
27#include "ar5416/ar5416reg.h"
28#include "ar5416/ar5416phy.h"
29
30#include "ah_eeprom_v14.h"	/* for owl_get_ntxchains() */
31
32/*
33 * Return the wireless modes (a,b,g,n,t) supported by hardware.
34 *
35 * This value is what is actually supported by the hardware
36 * and is unaffected by regulatory/country code settings.
37 *
38 */
39u_int
40ar5416GetWirelessModes(struct ath_hal *ah)
41{
42	u_int mode;
43	struct ath_hal_private *ahpriv = AH_PRIVATE(ah);
44	HAL_CAPABILITIES *pCap = &ahpriv->ah_caps;
45
46	mode = ar5212GetWirelessModes(ah);
47
48	/* Only enable HT modes if the NIC supports HT */
49	if (pCap->halHTSupport == AH_TRUE && (mode & HAL_MODE_11A))
50		mode |= HAL_MODE_11NA_HT20
51		     |  HAL_MODE_11NA_HT40PLUS
52		     |  HAL_MODE_11NA_HT40MINUS
53		     ;
54	if (pCap->halHTSupport == AH_TRUE && (mode & HAL_MODE_11G))
55		mode |= HAL_MODE_11NG_HT20
56		     |  HAL_MODE_11NG_HT40PLUS
57		     |  HAL_MODE_11NG_HT40MINUS
58		     ;
59	return mode;
60}
61
62/*
63 * Change the LED blinking pattern to correspond to the connectivity
64 */
65void
66ar5416SetLedState(struct ath_hal *ah, HAL_LED_STATE state)
67{
68	static const uint32_t ledbits[8] = {
69		AR_MAC_LED_ASSOC_NONE,		/* HAL_LED_INIT */
70		AR_MAC_LED_ASSOC_PEND,		/* HAL_LED_SCAN */
71		AR_MAC_LED_ASSOC_PEND,		/* HAL_LED_AUTH */
72		AR_MAC_LED_ASSOC_ACTIVE,	/* HAL_LED_ASSOC*/
73		AR_MAC_LED_ASSOC_ACTIVE,	/* HAL_LED_RUN */
74		AR_MAC_LED_ASSOC_NONE,
75		AR_MAC_LED_ASSOC_NONE,
76		AR_MAC_LED_ASSOC_NONE,
77	};
78
79	if (AR_SREV_HOWL(ah))
80		return;
81
82	/*
83	 * Set the blink operating mode.
84	 */
85	OS_REG_RMW_FIELD(ah, AR_MAC_LED,
86	    AR_MAC_LED_ASSOC, ledbits[state & 0x7]);
87
88	/* XXX Blink slow mode? */
89	/* XXX Blink threshold? */
90	/* XXX Blink sleep hystersis? */
91
92	/*
93	 * Set the LED blink configuration to be proportional
94	 * to the current TX and RX filter bytes.  (Ie, RX'ed
95	 * frames that don't match the filter are ignored.)
96	 * This means that higher TX/RX throughput will result
97	 * in the blink rate increasing.
98	 */
99	OS_REG_RMW_FIELD(ah, AR_MAC_LED, AR_MAC_LED_MODE,
100	    AR_MAC_LED_MODE_PROP);
101}
102
103/*
104 * Get the current hardware tsf for stamlme
105 */
106uint64_t
107ar5416GetTsf64(struct ath_hal *ah)
108{
109	uint32_t low1, low2, u32;
110
111	/* sync multi-word read */
112	low1 = OS_REG_READ(ah, AR_TSF_L32);
113	u32 = OS_REG_READ(ah, AR_TSF_U32);
114	low2 = OS_REG_READ(ah, AR_TSF_L32);
115	if (low2 < low1) {	/* roll over */
116		/*
117		 * If we are not preempted this will work.  If we are
118		 * then we re-reading AR_TSF_U32 does no good as the
119		 * low bits will be meaningless.  Likewise reading
120		 * L32, U32, U32, then comparing the last two reads
121		 * to check for rollover doesn't help if preempted--so
122		 * we take this approach as it costs one less PCI read
123		 * which can be noticeable when doing things like
124		 * timestamping packets in monitor mode.
125		 */
126		u32++;
127	}
128	return (((uint64_t) u32) << 32) | ((uint64_t) low2);
129}
130
131void
132ar5416SetTsf64(struct ath_hal *ah, uint64_t tsf64)
133{
134	OS_REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff);
135	OS_REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff);
136}
137
138/*
139 * Reset the current hardware tsf for stamlme.
140 */
141void
142ar5416ResetTsf(struct ath_hal *ah)
143{
144	uint32_t v;
145	int i;
146
147	for (i = 0; i < 10; i++) {
148		v = OS_REG_READ(ah, AR_SLP32_MODE);
149		if ((v & AR_SLP32_TSF_WRITE_STATUS) == 0)
150			break;
151		OS_DELAY(10);
152	}
153	OS_REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE);
154}
155
156uint32_t
157ar5416GetCurRssi(struct ath_hal *ah)
158{
159	if (AR_SREV_OWL(ah))
160		return (OS_REG_READ(ah, AR_PHY_CURRENT_RSSI) & 0xff);
161	return (OS_REG_READ(ah, AR9130_PHY_CURRENT_RSSI) & 0xff);
162}
163
164HAL_BOOL
165ar5416SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings)
166{
167	return AH_TRUE;
168}
169
170/* Setup decompression for given key index */
171HAL_BOOL
172ar5416SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en)
173{
174	return AH_TRUE;
175}
176
177/* Setup coverage class */
178void
179ar5416SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now)
180{
181	AH_PRIVATE(ah)->ah_coverageClass = coverageclass;
182}
183
184/*
185 * Return the busy for rx_frame, rx_clear, and tx_frame
186 */
187uint32_t
188ar5416GetMibCycleCountsPct(struct ath_hal *ah, uint32_t *rxc_pcnt,
189    uint32_t *extc_pcnt, uint32_t *rxf_pcnt, uint32_t *txf_pcnt)
190{
191	struct ath_hal_5416 *ahp = AH5416(ah);
192	u_int32_t good = 1;
193
194	/* XXX freeze/unfreeze mib counters */
195	uint32_t rc = OS_REG_READ(ah, AR_RCCNT);
196	uint32_t ec = OS_REG_READ(ah, AR_EXTRCCNT);
197	uint32_t rf = OS_REG_READ(ah, AR_RFCNT);
198	uint32_t tf = OS_REG_READ(ah, AR_TFCNT);
199	uint32_t cc = OS_REG_READ(ah, AR_CCCNT); /* read cycles last */
200
201	if (ahp->ah_cycleCount == 0 || ahp->ah_cycleCount > cc) {
202		/*
203		 * Cycle counter wrap (or initial call); it's not possible
204		 * to accurately calculate a value because the registers
205		 * right shift rather than wrap--so punt and return 0.
206		 */
207		HALDEBUG(ah, HAL_DEBUG_ANY,
208			    "%s: cycle counter wrap. ExtBusy = 0\n", __func__);
209			good = 0;
210	} else {
211		uint32_t cc_d = cc - ahp->ah_cycleCount;
212		uint32_t rc_d = rc - ahp->ah_ctlBusy;
213		uint32_t ec_d = ec - ahp->ah_extBusy;
214		uint32_t rf_d = rf - ahp->ah_rxBusy;
215		uint32_t tf_d = tf - ahp->ah_txBusy;
216
217		if (cc_d != 0) {
218			*rxc_pcnt = rc_d * 100 / cc_d;
219			*rxf_pcnt = rf_d * 100 / cc_d;
220			*txf_pcnt = tf_d * 100 / cc_d;
221			*extc_pcnt = ec_d * 100 / cc_d;
222		} else {
223			good = 0;
224		}
225	}
226	ahp->ah_cycleCount = cc;
227	ahp->ah_rxBusy = rf;
228	ahp->ah_ctlBusy = rc;
229	ahp->ah_txBusy = tf;
230	ahp->ah_extBusy = ec;
231
232	return good;
233}
234
235/*
236 * Return approximation of extension channel busy over an time interval
237 * 0% (clear) -> 100% (busy)
238 *
239 */
240uint32_t
241ar5416Get11nExtBusy(struct ath_hal *ah)
242{
243    struct ath_hal_5416 *ahp = AH5416(ah);
244    uint32_t busy; /* percentage */
245    uint32_t cycleCount, ctlBusy, extBusy;
246
247    ctlBusy = OS_REG_READ(ah, AR_RCCNT);
248    extBusy = OS_REG_READ(ah, AR_EXTRCCNT);
249    cycleCount = OS_REG_READ(ah, AR_CCCNT);
250
251    if (ahp->ah_cycleCount == 0 || ahp->ah_cycleCount > cycleCount) {
252        /*
253         * Cycle counter wrap (or initial call); it's not possible
254         * to accurately calculate a value because the registers
255         * right shift rather than wrap--so punt and return 0.
256         */
257        busy = 0;
258        HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cycle counter wrap. ExtBusy = 0\n",
259	    __func__);
260
261    } else {
262        uint32_t cycleDelta = cycleCount - ahp->ah_cycleCount;
263        uint32_t ctlBusyDelta = ctlBusy - ahp->ah_ctlBusy;
264        uint32_t extBusyDelta = extBusy - ahp->ah_extBusy;
265        uint32_t ctlClearDelta = 0;
266
267        /* Compute control channel rxclear.
268         * The cycle delta may be less than the control channel delta.
269         * This could be solved by freezing the timers (or an atomic read,
270         * if one was available). Checking for the condition should be
271         * sufficient.
272         */
273        if (cycleDelta > ctlBusyDelta) {
274            ctlClearDelta = cycleDelta - ctlBusyDelta;
275        }
276
277        /* Compute ratio of extension channel busy to control channel clear
278         * as an approximation to extension channel cleanliness.
279         *
280         * According to the hardware folks, ext rxclear is undefined
281         * if the ctrl rxclear is de-asserted (i.e. busy)
282         */
283        if (ctlClearDelta) {
284            busy = (extBusyDelta * 100) / ctlClearDelta;
285        } else {
286            busy = 100;
287        }
288        if (busy > 100) {
289            busy = 100;
290        }
291#if 0
292        HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cycleDelta 0x%x, ctlBusyDelta 0x%x, "
293             "extBusyDelta 0x%x, ctlClearDelta 0x%x, "
294             "busy %d\n",
295              __func__, cycleDelta, ctlBusyDelta, extBusyDelta, ctlClearDelta, busy);
296#endif
297    }
298
299    ahp->ah_cycleCount = cycleCount;
300    ahp->ah_ctlBusy = ctlBusy;
301    ahp->ah_extBusy = extBusy;
302
303    return busy;
304}
305
306/*
307 * Configure 20/40 operation
308 *
309 * 20/40 = joint rx clear (control and extension)
310 * 20    = rx clear (control)
311 *
312 * - NOTE: must stop MAC (tx) and requeue 40 MHz packets as 20 MHz when changing
313 *         from 20/40 => 20 only
314 */
315void
316ar5416Set11nMac2040(struct ath_hal *ah, HAL_HT_MACMODE mode)
317{
318    uint32_t macmode;
319
320    /* Configure MAC for 20/40 operation */
321    if (mode == HAL_HT_MACMODE_2040) {
322        macmode = AR_2040_JOINED_RX_CLEAR;
323    } else {
324        macmode = 0;
325    }
326    OS_REG_WRITE(ah, AR_2040_MODE, macmode);
327}
328
329/*
330 * Get Rx clear (control/extension channel)
331 *
332 * Returns active low (busy) for ctrl/ext channel
333 * Owl 2.0
334 */
335HAL_HT_RXCLEAR
336ar5416Get11nRxClear(struct ath_hal *ah)
337{
338    HAL_HT_RXCLEAR rxclear = 0;
339    uint32_t val;
340
341    val = OS_REG_READ(ah, AR_DIAG_SW);
342
343    /* control channel */
344    if (val & AR_DIAG_RXCLEAR_CTL_LOW) {
345        rxclear |= HAL_RX_CLEAR_CTL_LOW;
346    }
347    /* extension channel */
348    if (val & AR_DIAG_RXCLEAR_EXT_LOW) {
349        rxclear |= HAL_RX_CLEAR_EXT_LOW;
350    }
351    return rxclear;
352}
353
354/*
355 * Set Rx clear (control/extension channel)
356 *
357 * Useful for forcing the channel to appear busy for
358 * debugging/diagnostics
359 * Owl 2.0
360 */
361void
362ar5416Set11nRxClear(struct ath_hal *ah, HAL_HT_RXCLEAR rxclear)
363{
364    /* control channel */
365    if (rxclear & HAL_RX_CLEAR_CTL_LOW) {
366        OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_CTL_LOW);
367    } else {
368        OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_CTL_LOW);
369    }
370    /* extension channel */
371    if (rxclear & HAL_RX_CLEAR_EXT_LOW) {
372        OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_EXT_LOW);
373    } else {
374        OS_REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RXCLEAR_EXT_LOW);
375    }
376}
377
378/* XXX shouldn't be here! */
379#define	TU_TO_USEC(_tu)		((_tu) << 10)
380
381HAL_STATUS
382ar5416SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration,
383    uint32_t nextStart, HAL_QUIET_FLAG flag)
384{
385	uint32_t period_us = TU_TO_USEC(period); /* convert to us unit */
386	uint32_t nextStart_us = TU_TO_USEC(nextStart); /* convert to us unit */
387	if (flag & HAL_QUIET_ENABLE) {
388		if ((!nextStart) || (flag & HAL_QUIET_ADD_CURRENT_TSF)) {
389			/* Add the nextStart offset to the current TSF */
390			nextStart_us += OS_REG_READ(ah, AR_TSF_L32);
391		}
392		if (flag & HAL_QUIET_ADD_SWBA_RESP_TIME) {
393			nextStart_us += ah->ah_config.ah_sw_beacon_response_time;
394		}
395		OS_REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
396		OS_REG_WRITE(ah, AR_QUIET2, SM(duration, AR_QUIET2_QUIET_DUR));
397		OS_REG_WRITE(ah, AR_QUIET_PERIOD, period_us);
398		OS_REG_WRITE(ah, AR_NEXT_QUIET, nextStart_us);
399		OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET);
400	} else {
401		OS_REG_CLR_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET);
402	}
403	return HAL_OK;
404}
405#undef	TU_TO_USEC
406
407HAL_STATUS
408ar5416GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
409        uint32_t capability, uint32_t *result)
410{
411	switch (type) {
412	case HAL_CAP_BB_HANG:
413		switch (capability) {
414		case HAL_BB_HANG_RIFS:
415			return (AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) ? HAL_OK : HAL_ENOTSUPP;
416		case HAL_BB_HANG_DFS:
417			return (AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) ? HAL_OK : HAL_ENOTSUPP;
418		case HAL_BB_HANG_RX_CLEAR:
419			return AR_SREV_MERLIN(ah) ? HAL_OK : HAL_ENOTSUPP;
420		}
421		break;
422	case HAL_CAP_MAC_HANG:
423		return ((ah->ah_macVersion == AR_XSREV_VERSION_OWL_PCI) ||
424		    (ah->ah_macVersion == AR_XSREV_VERSION_OWL_PCIE) ||
425		    AR_SREV_HOWL(ah) || AR_SREV_SOWL(ah)) ?
426			HAL_OK : HAL_ENOTSUPP;
427	case HAL_CAP_DIVERSITY:		/* disable classic fast diversity */
428		return HAL_ENXIO;
429	default:
430		break;
431	}
432	return ar5212GetCapability(ah, type, capability, result);
433}
434
435HAL_BOOL
436ar5416SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
437    u_int32_t capability, u_int32_t setting, HAL_STATUS *status)
438{
439	HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
440
441	switch (type) {
442	case HAL_CAP_RX_CHAINMASK:
443		setting &= ath_hal_eepromGet(ah, AR_EEP_RXMASK, NULL);
444		pCap->halRxChainMask = setting;
445		if (owl_get_ntxchains(setting) > 2)
446			pCap->halRxStreams = 2;
447		else
448			pCap->halRxStreams = 1;
449		return AH_TRUE;
450	case HAL_CAP_TX_CHAINMASK:
451		setting &= ath_hal_eepromGet(ah, AR_EEP_TXMASK, NULL);
452		pCap->halTxChainMask = setting;
453		if (owl_get_ntxchains(setting) > 2)
454			pCap->halTxStreams = 2;
455		else
456			pCap->halTxStreams = 1;
457		return AH_TRUE;
458	default:
459		break;
460	}
461	return ar5212SetCapability(ah, type, capability, setting, status);
462}
463
464static int ar5416DetectMacHang(struct ath_hal *ah);
465static int ar5416DetectBBHang(struct ath_hal *ah);
466
467HAL_BOOL
468ar5416GetDiagState(struct ath_hal *ah, int request,
469	const void *args, uint32_t argsize,
470	void **result, uint32_t *resultsize)
471{
472	struct ath_hal_5416 *ahp = AH5416(ah);
473	int hangs;
474
475	if (ath_hal_getdiagstate(ah, request, args, argsize, result, resultsize))
476		return AH_TRUE;
477	switch (request) {
478	case HAL_DIAG_EEPROM:
479		return ath_hal_eepromDiag(ah, request,
480		    args, argsize, result, resultsize);
481	case HAL_DIAG_CHECK_HANGS:
482		if (argsize != sizeof(int))
483			return AH_FALSE;
484		hangs = *(const int *) args;
485		ahp->ah_hangs = 0;
486		if (hangs & HAL_BB_HANGS)
487			ahp->ah_hangs |= ar5416DetectBBHang(ah);
488		/* NB: if BB is hung MAC will be hung too so skip check */
489		if (ahp->ah_hangs == 0 && (hangs & HAL_MAC_HANGS))
490			ahp->ah_hangs |= ar5416DetectMacHang(ah);
491		*result = &ahp->ah_hangs;
492		*resultsize = sizeof(ahp->ah_hangs);
493		return AH_TRUE;
494	}
495	return ar5212GetDiagState(ah, request,
496	    args, argsize, result, resultsize);
497}
498
499typedef struct {
500	uint32_t dma_dbg_3;
501	uint32_t dma_dbg_4;
502	uint32_t dma_dbg_5;
503	uint32_t dma_dbg_6;
504} mac_dbg_regs_t;
505
506typedef enum {
507	dcu_chain_state		= 0x1,
508	dcu_complete_state	= 0x2,
509	qcu_state		= 0x4,
510	qcu_fsp_ok		= 0x8,
511	qcu_fsp_state		= 0x10,
512	qcu_stitch_state	= 0x20,
513	qcu_fetch_state		= 0x40,
514	qcu_complete_state	= 0x80
515} hal_mac_hangs_t;
516
517typedef struct {
518	int states;
519	uint8_t dcu_chain_state;
520	uint8_t dcu_complete_state;
521	uint8_t qcu_state;
522	uint8_t qcu_fsp_ok;
523	uint8_t qcu_fsp_state;
524	uint8_t qcu_stitch_state;
525	uint8_t qcu_fetch_state;
526	uint8_t qcu_complete_state;
527} hal_mac_hang_check_t;
528
529HAL_BOOL
530ar5416SetRifsDelay(struct ath_hal *ah, const struct ieee80211_channel *chan,
531    HAL_BOOL enable)
532{
533	uint32_t val;
534	HAL_BOOL is_chan_2g = AH_FALSE;
535	HAL_BOOL is_ht40 = AH_FALSE;
536
537	if (chan)
538		is_chan_2g = IEEE80211_IS_CHAN_2GHZ(chan);
539
540	if (chan)
541		is_ht40 = IEEE80211_IS_CHAN_HT40(chan);
542
543	/* Only support disabling RIFS delay for now */
544	HALASSERT(enable == AH_FALSE);
545
546	if (enable == AH_TRUE)
547		return AH_FALSE;
548
549	/* Change RIFS init delay to 0 */
550	val = OS_REG_READ(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS);
551	val &= ~AR_PHY_RIFS_INIT_DELAY;
552	OS_REG_WRITE(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS, val);
553
554	/*
555	 * For Owl, RIFS RX parameters are controlled differently;
556	 * it isn't enabled in the inivals by default.
557	 *
558	 * For Sowl/Howl, RIFS RX is enabled in the inivals by default;
559	 * the following code sets them back to non-RIFS values.
560	 *
561	 * For > Sowl/Howl, RIFS RX can be left on by default and so
562	 * this function shouldn't be called.
563	 */
564	if ((! AR_SREV_SOWL(ah)) && (! AR_SREV_HOWL(ah)))
565		return AH_TRUE;
566
567	/* Reset search delay to default values */
568	if (is_chan_2g)
569		if (is_ht40)
570			OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x268);
571		else
572			OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x134);
573	else
574		if (is_ht40)
575			OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x370);
576		else
577			OS_REG_WRITE(ah, AR_PHY_SEARCH_START_DELAY, 0x1b8);
578
579	return AH_TRUE;
580}
581
582static HAL_BOOL
583ar5416CompareDbgHang(struct ath_hal *ah, const mac_dbg_regs_t *regs,
584    const hal_mac_hang_check_t *check)
585{
586	int found_states;
587
588	found_states = 0;
589	if (check->states & dcu_chain_state) {
590		int i;
591
592		for (i = 0; i < 6; i++) {
593			if (((regs->dma_dbg_4 >> (5*i)) & 0x1f) ==
594			    check->dcu_chain_state)
595				found_states |= dcu_chain_state;
596		}
597		for (i = 0; i < 4; i++) {
598			if (((regs->dma_dbg_5 >> (5*i)) & 0x1f) ==
599			    check->dcu_chain_state)
600				found_states |= dcu_chain_state;
601		}
602	}
603	if (check->states & dcu_complete_state) {
604		if ((regs->dma_dbg_6 & 0x3) == check->dcu_complete_state)
605			found_states |= dcu_complete_state;
606	}
607	if (check->states & qcu_stitch_state) {
608		if (((regs->dma_dbg_3 >> 18) & 0xf) == check->qcu_stitch_state)
609			found_states |= qcu_stitch_state;
610	}
611	if (check->states & qcu_fetch_state) {
612		if (((regs->dma_dbg_3 >> 22) & 0xf) == check->qcu_fetch_state)
613			found_states |= qcu_fetch_state;
614	}
615	if (check->states & qcu_complete_state) {
616		if (((regs->dma_dbg_3 >> 26) & 0x7) == check->qcu_complete_state)
617			found_states |= qcu_complete_state;
618	}
619	return (found_states == check->states);
620}
621
622#define NUM_STATUS_READS 50
623
624static int
625ar5416DetectMacHang(struct ath_hal *ah)
626{
627	static const hal_mac_hang_check_t hang_sig1 = {
628		.dcu_chain_state	= 0x6,
629		.dcu_complete_state	= 0x1,
630		.states			= dcu_chain_state
631					| dcu_complete_state,
632	};
633	static const hal_mac_hang_check_t hang_sig2 = {
634		.qcu_stitch_state	= 0x9,
635		.qcu_fetch_state	= 0x8,
636		.qcu_complete_state	= 0x4,
637		.states			= qcu_stitch_state
638					| qcu_fetch_state
639					| qcu_complete_state,
640        };
641	mac_dbg_regs_t mac_dbg;
642	int i;
643
644	mac_dbg.dma_dbg_3 = OS_REG_READ(ah, AR_DMADBG_3);
645	mac_dbg.dma_dbg_4 = OS_REG_READ(ah, AR_DMADBG_4);
646	mac_dbg.dma_dbg_5 = OS_REG_READ(ah, AR_DMADBG_5);
647	mac_dbg.dma_dbg_6 = OS_REG_READ(ah, AR_DMADBG_6);
648	for (i = 1; i <= NUM_STATUS_READS; i++) {
649		if (mac_dbg.dma_dbg_3 != OS_REG_READ(ah, AR_DMADBG_3) ||
650		    mac_dbg.dma_dbg_4 != OS_REG_READ(ah, AR_DMADBG_4) ||
651		    mac_dbg.dma_dbg_5 != OS_REG_READ(ah, AR_DMADBG_5) ||
652		    mac_dbg.dma_dbg_6 != OS_REG_READ(ah, AR_DMADBG_6))
653			return 0;
654	}
655
656	if (ar5416CompareDbgHang(ah, &mac_dbg, &hang_sig1))
657		return HAL_MAC_HANG_SIG1;
658	if (ar5416CompareDbgHang(ah, &mac_dbg, &hang_sig2))
659		return HAL_MAC_HANG_SIG2;
660
661	HALDEBUG(ah, HAL_DEBUG_HANG, "%s Found an unknown MAC hang signature "
662	    "DMADBG_3=0x%x DMADBG_4=0x%x DMADBG_5=0x%x DMADBG_6=0x%x\n",
663	    __func__, mac_dbg.dma_dbg_3, mac_dbg.dma_dbg_4, mac_dbg.dma_dbg_5,
664	    mac_dbg.dma_dbg_6);
665
666	return 0;
667}
668
669/*
670 * Determine if the baseband using the Observation Bus Register
671 */
672static int
673ar5416DetectBBHang(struct ath_hal *ah)
674{
675#define N(a) (sizeof(a)/sizeof(a[0]))
676	/*
677	 * Check the PCU Observation Bus 1 register (0x806c)
678	 * NUM_STATUS_READS times
679	 *
680	 * 4 known BB hang signatures -
681	 * [1] bits 8,9,11 are 0. State machine state (bits 25-31) is 0x1E
682	 * [2] bits 8,9 are 1, bit 11 is 0. State machine state
683	 *     (bits 25-31) is 0x52
684	 * [3] bits 8,9 are 1, bit 11 is 0. State machine state
685	 *     (bits 25-31) is 0x18
686	 * [4] bit 10 is 1, bit 11 is 0. WEP state (bits 12-17) is 0x2,
687	 *     Rx State (bits 20-24) is 0x7.
688	 */
689	static const struct {
690		uint32_t val;
691		uint32_t mask;
692		int code;
693	} hang_list[] = {
694		/* Reg Value   Reg Mask    Hang Code XXX */
695		{ 0x1E000000, 0x7E000B00, HAL_BB_HANG_DFS },
696		{ 0x52000B00, 0x7E000B00, HAL_BB_HANG_RIFS },
697		{ 0x18000B00, 0x7E000B00, HAL_BB_HANG_RX_CLEAR },
698		{ 0x00702400, 0x7E7FFFEF, HAL_BB_HANG_RX_CLEAR }
699	};
700	uint32_t hang_sig;
701	int i;
702
703	hang_sig = OS_REG_READ(ah, AR_OBSERV_1);
704	for (i = 1; i <= NUM_STATUS_READS; i++) {
705		if (hang_sig != OS_REG_READ(ah, AR_OBSERV_1))
706			return 0;
707	}
708	for (i = 0; i < N(hang_list); i++)
709		if ((hang_sig & hang_list[i].mask) == hang_list[i].val) {
710			HALDEBUG(ah, HAL_DEBUG_HANG,
711			    "%s BB hang, signature 0x%x, code 0x%x\n",
712			    __func__, hang_sig, hang_list[i].code);
713			return hang_list[i].code;
714		}
715
716	HALDEBUG(ah, HAL_DEBUG_HANG, "%s Found an unknown BB hang signature! "
717	    "<0x806c>=0x%x\n", __func__, hang_sig);
718
719	return 0;
720#undef N
721}
722#undef NUM_STATUS_READS
723
724/*
725 * Get the radar parameter values and return them in the pe
726 * structure
727 */
728void
729ar5416GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
730{
731	uint32_t val, temp;
732
733	val = OS_REG_READ(ah, AR_PHY_RADAR_0);
734
735	temp = MS(val,AR_PHY_RADAR_0_FIRPWR);
736	temp |= 0xFFFFFF80;
737	pe->pe_firpwr = temp;
738	pe->pe_rrssi = MS(val, AR_PHY_RADAR_0_RRSSI);
739	pe->pe_height =  MS(val, AR_PHY_RADAR_0_HEIGHT);
740	pe->pe_prssi = MS(val, AR_PHY_RADAR_0_PRSSI);
741	pe->pe_inband = MS(val, AR_PHY_RADAR_0_INBAND);
742
743	/* RADAR_1 values */
744	val = OS_REG_READ(ah, AR_PHY_RADAR_1);
745	pe->pe_relpwr = MS(val, AR_PHY_RADAR_1_RELPWR_THRESH);
746	pe->pe_relstep = MS(val, AR_PHY_RADAR_1_RELSTEP_THRESH);
747	pe->pe_maxlen = MS(val, AR_PHY_RADAR_1_MAXLEN);
748
749	pe->pe_extchannel = !! (OS_REG_READ(ah, AR_PHY_RADAR_EXT) &
750	    AR_PHY_RADAR_EXT_ENA);
751
752	pe->pe_usefir128 = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
753	    AR_PHY_RADAR_1_USE_FIR128);
754	pe->pe_blockradar = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
755	    AR_PHY_RADAR_1_BLOCK_CHECK);
756	pe->pe_enmaxrssi = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
757	    AR_PHY_RADAR_1_MAX_RRSSI);
758	pe->pe_enabled = !!
759	    (OS_REG_READ(ah, AR_PHY_RADAR_0) & AR_PHY_RADAR_0_ENA);
760	pe->pe_enrelpwr = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
761	    AR_PHY_RADAR_1_RELPWR_ENA);
762	pe->pe_en_relstep_check = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
763	    AR_PHY_RADAR_1_RELSTEP_CHECK);
764}
765
766/*
767 * Enable radar detection and set the radar parameters per the
768 * values in pe
769 */
770void
771ar5416EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
772{
773	uint32_t val;
774
775	val = OS_REG_READ(ah, AR_PHY_RADAR_0);
776
777	if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) {
778		val &= ~AR_PHY_RADAR_0_FIRPWR;
779		val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR);
780	}
781	if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) {
782		val &= ~AR_PHY_RADAR_0_RRSSI;
783		val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI);
784	}
785	if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) {
786		val &= ~AR_PHY_RADAR_0_HEIGHT;
787		val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT);
788	}
789	if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) {
790		val &= ~AR_PHY_RADAR_0_PRSSI;
791		val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI);
792	}
793	if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) {
794		val &= ~AR_PHY_RADAR_0_INBAND;
795		val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND);
796	}
797
798	/*Enable FFT data*/
799	val |= AR_PHY_RADAR_0_FFT_ENA;
800	OS_REG_WRITE(ah, AR_PHY_RADAR_0, val);
801
802	/* Implicitly enable */
803	if (pe->pe_enabled == 1)
804		OS_REG_SET_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA);
805	else if (pe->pe_enabled == 0)
806		OS_REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA);
807
808	if (pe->pe_usefir128 == 1)
809		OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_USE_FIR128);
810	else if (pe->pe_usefir128 == 0)
811		OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_USE_FIR128);
812
813	if (pe->pe_enmaxrssi == 1)
814		OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_MAX_RRSSI);
815	else if (pe->pe_enmaxrssi == 0)
816		OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_MAX_RRSSI);
817
818	if (pe->pe_blockradar == 1)
819		OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_BLOCK_CHECK);
820	else if (pe->pe_blockradar == 0)
821		OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_BLOCK_CHECK);
822
823	if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL) {
824		val = OS_REG_READ(ah, AR_PHY_RADAR_1);
825		val &= ~AR_PHY_RADAR_1_RELSTEP_THRESH;
826		val |= SM(pe->pe_relstep, AR_PHY_RADAR_1_RELSTEP_THRESH);
827		OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);
828	}
829	if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL) {
830		val = OS_REG_READ(ah, AR_PHY_RADAR_1);
831		val &= ~AR_PHY_RADAR_1_RELPWR_THRESH;
832		val |= SM(pe->pe_relpwr, AR_PHY_RADAR_1_RELPWR_THRESH);
833		OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);
834	}
835
836	if (pe->pe_en_relstep_check == 1)
837		OS_REG_SET_BIT(ah, AR_PHY_RADAR_1,
838		    AR_PHY_RADAR_1_RELSTEP_CHECK);
839	else if (pe->pe_en_relstep_check == 0)
840		OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1,
841		    AR_PHY_RADAR_1_RELSTEP_CHECK);
842
843	if (pe->pe_enrelpwr == 1)
844		OS_REG_SET_BIT(ah, AR_PHY_RADAR_1,
845		    AR_PHY_RADAR_1_RELPWR_ENA);
846	else if (pe->pe_enrelpwr == 0)
847		OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1,
848		    AR_PHY_RADAR_1_RELPWR_ENA);
849
850	if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL) {
851		val = OS_REG_READ(ah, AR_PHY_RADAR_1);
852		val &= ~AR_PHY_RADAR_1_MAXLEN;
853		val |= SM(pe->pe_maxlen, AR_PHY_RADAR_1_MAXLEN);
854		OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);
855	}
856
857	/*
858	 * Enable HT/40 if the upper layer asks;
859	 * it should check the channel is HT/40 and HAL_CAP_EXT_CHAN_DFS
860	 * is available.
861	 */
862	if (pe->pe_extchannel == 1)
863		OS_REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
864	else if (pe->pe_extchannel == 0)
865		OS_REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
866}
867
868/*
869 * Extract the radar event information from the given phy error.
870 *
871 * Returns AH_TRUE if the phy error was actually a phy error,
872 * AH_FALSE if the phy error wasn't a phy error.
873 */
874
875/* Flags for pulse_bw_info */
876#define	PRI_CH_RADAR_FOUND		0x01
877#define	EXT_CH_RADAR_FOUND		0x02
878#define	EXT_CH_RADAR_EARLY_FOUND	0x04
879
880HAL_BOOL
881ar5416ProcessRadarEvent(struct ath_hal *ah, struct ath_rx_status *rxs,
882    uint64_t fulltsf, const char *buf, HAL_DFS_EVENT *event)
883{
884	HAL_BOOL doDfsExtCh;
885	HAL_BOOL doDfsEnhanced;
886	HAL_BOOL doDfsCombinedRssi;
887
888	uint8_t rssi = 0, ext_rssi = 0;
889	uint8_t pulse_bw_info = 0, pulse_length_ext = 0, pulse_length_pri = 0;
890	uint32_t dur = 0;
891	int pri_found = 1, ext_found = 0;
892	int early_ext = 0;
893	int is_dc = 0;
894	uint16_t datalen;		/* length from the RX status field */
895
896	/* Check whether the given phy error is a radar event */
897	if ((rxs->rs_phyerr != HAL_PHYERR_RADAR) &&
898	    (rxs->rs_phyerr != HAL_PHYERR_FALSE_RADAR_EXT)) {
899		return AH_FALSE;
900	}
901
902	/* Grab copies of the capabilities; just to make the code clearer */
903	doDfsExtCh = AH_PRIVATE(ah)->ah_caps.halExtChanDfsSupport;
904	doDfsEnhanced = AH_PRIVATE(ah)->ah_caps.halEnhancedDfsSupport;
905	doDfsCombinedRssi = AH_PRIVATE(ah)->ah_caps.halUseCombinedRadarRssi;
906
907	datalen = rxs->rs_datalen;
908
909	/* If hardware supports it, use combined RSSI, else use chain 0 RSSI */
910	if (doDfsCombinedRssi)
911		rssi = (uint8_t) rxs->rs_rssi;
912	else
913		rssi = (uint8_t) rxs->rs_rssi_ctl[0];
914
915	/* Set this; but only use it if doDfsExtCh is set */
916	ext_rssi = (uint8_t) rxs->rs_rssi_ext[0];
917
918	/* Cap it at 0 if the RSSI is a negative number */
919	if (rssi & 0x80)
920		rssi = 0;
921
922	if (ext_rssi & 0x80)
923		ext_rssi = 0;
924
925	/*
926	 * Fetch the relevant data from the frame
927	 */
928	if (doDfsExtCh) {
929		if (datalen < 3)
930			return AH_FALSE;
931
932		/* Last three bytes of the frame are of interest */
933		pulse_length_pri = *(buf + datalen - 3);
934		pulse_length_ext = *(buf + datalen - 2);
935		pulse_bw_info = *(buf + datalen - 1);
936		HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, ext_rssi=%d, pulse_length_pri=%d,"
937		    " pulse_length_ext=%d, pulse_bw_info=%x\n",
938		    __func__, rssi, ext_rssi, pulse_length_pri, pulse_length_ext,
939		    pulse_bw_info);
940	} else {
941		/* The pulse width is byte 0 of the data */
942		if (datalen >= 1)
943			dur = ((uint8_t) buf[0]) & 0xff;
944		else
945			dur = 0;
946
947		if (dur == 0 && rssi == 0) {
948			HALDEBUG(ah, HAL_DEBUG_DFS, "%s: dur and rssi are 0\n", __func__);
949			return AH_FALSE;
950		}
951
952		HALDEBUG(ah, HAL_DEBUG_DFS, "%s: rssi=%d, dur=%d\n", __func__, rssi, dur);
953
954		/* Single-channel only */
955		pri_found = 1;
956		ext_found = 0;
957	}
958
959	/*
960	 * If doing extended channel data, pulse_bw_info must
961	 * have one of the flags set.
962	 */
963	if (doDfsExtCh && pulse_bw_info == 0x0)
964		return AH_FALSE;
965
966	/*
967	 * If the extended channel data is available, calculate
968	 * which to pay attention to.
969	 */
970	if (doDfsExtCh) {
971		/* If pulse is on DC, take the larger duration of the two */
972		if ((pulse_bw_info & EXT_CH_RADAR_FOUND) &&
973		    (pulse_bw_info & PRI_CH_RADAR_FOUND)) {
974			is_dc = 1;
975			if (pulse_length_ext > pulse_length_pri) {
976				dur = pulse_length_ext;
977				pri_found = 0;
978				ext_found = 1;
979			} else {
980				dur = pulse_length_pri;
981				pri_found = 1;
982				ext_found = 0;
983			}
984		} else if (pulse_bw_info & EXT_CH_RADAR_EARLY_FOUND) {
985			dur = pulse_length_ext;
986			pri_found = 0;
987			ext_found = 1;
988			early_ext = 1;
989		} else if (pulse_bw_info & PRI_CH_RADAR_FOUND) {
990			dur = pulse_length_pri;
991			pri_found = 1;
992			ext_found = 0;
993		} else if (pulse_bw_info & EXT_CH_RADAR_FOUND) {
994			dur = pulse_length_ext;
995			pri_found = 0;
996			ext_found = 1;
997		}
998
999	}
1000
1001	/*
1002	 * For enhanced DFS (Merlin and later), pulse_bw_info has
1003	 * implications for selecting the correct RSSI value.
1004	 */
1005	if (doDfsEnhanced) {
1006		switch (pulse_bw_info & 0x03) {
1007		case 0:
1008			/* No radar? */
1009			rssi = 0;
1010			break;
1011		case PRI_CH_RADAR_FOUND:
1012			/* Radar in primary channel */
1013			/* Cannot use ctrl channel RSSI if ext channel is stronger */
1014			if (ext_rssi >= (rssi + 3)) {
1015				rssi = 0;
1016			};
1017			break;
1018		case EXT_CH_RADAR_FOUND:
1019			/* Radar in extended channel */
1020			/* Cannot use ext channel RSSI if ctrl channel is stronger */
1021			if (rssi >= (ext_rssi + 12)) {
1022				rssi = 0;
1023			} else {
1024				rssi = ext_rssi;
1025			}
1026			break;
1027		case (PRI_CH_RADAR_FOUND | EXT_CH_RADAR_FOUND):
1028			/* When both are present, use stronger one */
1029			if (rssi < ext_rssi)
1030				rssi = ext_rssi;
1031			break;
1032		}
1033	}
1034
1035	/*
1036	 * If not doing enhanced DFS, choose the ext channel if
1037	 * it is stronger than the main channel
1038	 */
1039	if (doDfsExtCh && !doDfsEnhanced) {
1040		if ((ext_rssi > rssi) && (ext_rssi < 128))
1041			rssi = ext_rssi;
1042	}
1043
1044	/*
1045	 * XXX what happens if the above code decides the RSSI
1046	 * XXX wasn't valid, an sets it to 0?
1047	 */
1048
1049	/*
1050	 * Fill out dfs_event structure.
1051	 */
1052	event->re_full_ts = fulltsf;
1053	event->re_ts = rxs->rs_tstamp;
1054	event->re_rssi = rssi;
1055	event->re_dur = dur;
1056
1057	event->re_flags = 0;
1058	if (pri_found)
1059		event->re_flags |= HAL_DFS_EVENT_PRICH;
1060	if (ext_found)
1061		event->re_flags |= HAL_DFS_EVENT_EXTCH;
1062	if (early_ext)
1063		event->re_flags |= HAL_DFS_EVENT_EXTEARLY;
1064	if (is_dc)
1065		event->re_flags |= HAL_DFS_EVENT_ISDC;
1066
1067	return AH_TRUE;
1068}
1069
1070/*
1071 * Return whether fast-clock is currently enabled for this
1072 * channel.
1073 */
1074HAL_BOOL
1075ar5416IsFastClockEnabled(struct ath_hal *ah)
1076{
1077	struct ath_hal_private *ahp = AH_PRIVATE(ah);
1078
1079	return IS_5GHZ_FAST_CLOCK_EN(ah, ahp->ah_curchan);
1080}
1081