/*
 * Copyright (c) 2002-2014 The Linux Foundation. All rights reserved.
 *
 * Previously licensed under the ISC license by Qualcomm Atheros, 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.
 */

/*
 * This file was originally distributed by Qualcomm Atheros, Inc.
 * under proprietary terms before Copyright ownership was assigned
 * to the Linux Foundation.
 */

/*===========================================================================

                              dfs_debug.c

   OVERVIEW:

   Source code borrowed from QCA_MAIN DFS module

   DEPENDENCIES:

   Are listed for each API below.

   ===========================================================================*/

/*===========================================================================

                      EDIT HISTORY FOR FILE

   This section contains comments describing changes made to the module.
   Notice that changes are listed in reverse chronological order.

   when        who     what, where, why
   ----------    ---    --------------------------------------------------------

   ===========================================================================*/

#include "dfs.h"
/* TO DO DFS
   #include <ieee80211_var.h>
 */
#ifdef ATH_SUPPORT_DFS

void dfs_print_delayline(struct ath_dfs *dfs, struct dfs_delayline *dl)
{
	int i = 0, index;
	struct dfs_delayelem *de;

	index = dl->dl_lastelem;
	for (i = 0; i < dl->dl_numelems; i++) {
		de = &dl->dl_elems[index];
		DFS_DPRINTK(dfs, ATH_DEBUG_DFS2,
			    "Elem %d: ts = %u (0x%x) dur=%u\n", i,
			    de->de_time, de->de_time, de->de_dur);
		index = (index - 1) & DFS_MAX_DL_MASK;
	}
}

void dfs_print_filter(struct ath_dfs *dfs, struct dfs_filter *rf)
{

	DFS_DPRINTK(dfs, ATH_DEBUG_DFS1,
		    "filterID[%d] rf_numpulses=%u; rf->rf_minpri=%u; "
		    "rf->rf_maxpri=%u; rf->rf_threshold=%u; rf->rf_filterlen=%u; "
		    "rf->rf_mindur=%u; rf->rf_maxdur=%u\n",
		    rf->rf_pulseid,
		    rf->rf_numpulses,
		    rf->rf_minpri,
		    rf->rf_maxpri,
		    rf->rf_threshold,
		    rf->rf_filterlen, rf->rf_mindur, rf->rf_maxdur);
}

void dfs_print_filters(struct ath_dfs *dfs)
{
	struct dfs_filtertype *ft = NULL;
	struct dfs_filter *rf;
	int i, j;

	if (dfs == NULL) {
		DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: sc_dfs is NULL\n",
			    __func__);
		return;
	}
	for (i = 0; i < DFS_MAX_RADAR_TYPES; i++) {
		if (dfs->dfs_radarf[i] != NULL) {
			ft = dfs->dfs_radarf[i];
			if ((ft->ft_numfilters > DFS_MAX_NUM_RADAR_FILTERS)
			    || (!ft->ft_numfilters))
				continue;
			DFS_PRINTK
				("===========ft->ft_numfilters=%u===========\n",
				ft->ft_numfilters);
			for (j = 0; j < ft->ft_numfilters; j++) {
				rf = &(ft->ft_filters[j]);
				DFS_PRINTK
					("filter[%d] filterID = %d rf_numpulses=%u; rf->rf_minpri=%u; rf->rf_maxpri=%u; rf->rf_threshold=%u; rf->rf_filterlen=%u; rf->rf_mindur=%u; rf->rf_maxdur=%u\n",
					j, rf->rf_pulseid, rf->rf_numpulses,
					rf->rf_minpri, rf->rf_maxpri,
					rf->rf_threshold, rf->rf_filterlen,
					rf->rf_mindur, rf->rf_maxdur);
			}
		}
	}
}

void dfs_print_activity(struct ath_dfs *dfs)
{
	int chan_busy = 0, ext_chan_busy = 0;
	uint32_t rxclear = 0, rxframe = 0, txframe = 0, cycles = 0;

	cycles =
		dfs->ic->ic_get_mib_cycle_counts_pct(dfs->ic, &rxclear, &rxframe,
						     &txframe);
	chan_busy = cycles;

	ext_chan_busy = dfs->ic->ic_get_ext_busy(dfs->ic);

	DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "cycles=%d rxclear=%d rxframe=%d"
		    " txframe=%d extchanbusy=%d\n", cycles, rxclear,
		    rxframe, txframe, ext_chan_busy);
	return;
}

/*
 * XXX migrate this to use ath_dfs as the arg, not ieee80211com!
 */
#ifndef ATH_DFS_RADAR_DETECTION_ONLY
os_timer_func(dfs_debug_timeout)
{
	struct ieee80211com *ic;
	struct ath_dfs *dfs;

	OS_GET_TIMER_ARG(ic, struct ieee80211com *);

	dfs = (struct ath_dfs *)ic->ic_dfs;

	dfs_print_activity(dfs);

	OS_SET_TIMER(&dfs->ath_dfs_debug_timer, DFS_DEBUG_TIMEOUT_MS);
}
#endif

#endif /* ATH_SUPPORT_DFS */
