/*
 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *
 * File: int.c
 *
 * Purpose: Handle USB interrupt endpoint
 *
 * Author: Jerry Chen
 *
 * Date: Apr. 2, 2004
 *
 * Functions:
 *
 * Revision History:
 *      04-02-2004 Jerry Chen:  Initial release
 *
 */

#include "int.h"
#include "mib.h"
#include "tmacro.h"
#include "mac.h"
#include "power.h"
#include "bssdb.h"
#include "usbpipe.h"

/*---------------------  Static Definitions -------------------------*/
static int msglevel = MSG_LEVEL_INFO; /* MSG_LEVEL_DEBUG */

/*---------------------  Static Classes  ----------------------------*/

/*---------------------  Static Variables  --------------------------*/

/*---------------------  Static Functions  --------------------------*/

/*---------------------  Export Variables  --------------------------*/

/*---------------------  Export Functions  --------------------------*/

/*+
 *
 *  Function:   InterruptPollingThread
 *
 *  Synopsis:   Thread running at IRQL PASSIVE_LEVEL.
 *
 *  Arguments: Device Extension
 *
 *  Returns:
 *
 *  Algorithm:  Call USBD for input data;
 *
 *  History:    dd-mm-yyyy   Author    Comment
 *
 *
 *  Notes:
 *
 *  USB reads are by nature 'Blocking', and when in a read, the device looks
 *  like it's in a 'stall' condition, so we deliberately time out every second
 *  if we've gotten no data
 *
-*/
void INTvWorkItem(void *Context)
{
	PSDevice pDevice = Context;
	int ntStatus;

	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Interrupt Polling Thread\n");

	spin_lock_irq(&pDevice->lock);
	if (pDevice->fKillEventPollingThread != TRUE)
		ntStatus = PIPEnsInterruptRead(pDevice);
	spin_unlock_irq(&pDevice->lock);
}

void INTnsProcessData(PSDevice pDevice)
{
	PSINTData pINTData;
	PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
	struct net_device_stats *pStats = &pDevice->stats;

	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->s_nsInterruptProcessData\n");

	pINTData = (PSINTData) pDevice->intBuf.pDataBuf;
	if (pINTData->byTSR0 & TSR_VALID) {
		STAvUpdateTDStatCounter(&(pDevice->scStatistic),
					(BYTE)(pINTData->byPkt0 & 0x0F),
					(BYTE)(pINTData->byPkt0>>4),
					pINTData->byTSR0);
		BSSvUpdateNodeTxCounter(pDevice,
					&(pDevice->scStatistic),
					pINTData->byTSR0,
					pINTData->byPkt0);
		/*DBG_PRN_GRP01(("TSR0 %02x\n", pINTData->byTSR0));*/
	}
	if (pINTData->byTSR1 & TSR_VALID) {
		STAvUpdateTDStatCounter(&(pDevice->scStatistic),
					(BYTE)(pINTData->byPkt1 & 0x0F),
					(BYTE)(pINTData->byPkt1>>4),
					pINTData->byTSR1);
		BSSvUpdateNodeTxCounter(pDevice,
					&(pDevice->scStatistic),
					pINTData->byTSR1,
					pINTData->byPkt1);
		/*DBG_PRN_GRP01(("TSR1 %02x\n", pINTData->byTSR1));*/
	}
	if (pINTData->byTSR2 & TSR_VALID) {
		STAvUpdateTDStatCounter(&(pDevice->scStatistic),
					(BYTE)(pINTData->byPkt2 & 0x0F),
					(BYTE)(pINTData->byPkt2>>4),
					pINTData->byTSR2);
		BSSvUpdateNodeTxCounter(pDevice,
					&(pDevice->scStatistic),
					pINTData->byTSR2,
					pINTData->byPkt2);
		/*DBG_PRN_GRP01(("TSR2 %02x\n", pINTData->byTSR2));*/
	}
	if (pINTData->byTSR3 & TSR_VALID) {
		STAvUpdateTDStatCounter(&(pDevice->scStatistic),
					(BYTE)(pINTData->byPkt3 & 0x0F),
					(BYTE)(pINTData->byPkt3>>4),
					pINTData->byTSR3);
		BSSvUpdateNodeTxCounter(pDevice,
					&(pDevice->scStatistic),
					pINTData->byTSR3,
					pINTData->byPkt3);
		/*DBG_PRN_GRP01(("TSR3 %02x\n", pINTData->byTSR3));*/
	}
	if (pINTData->byISR0 != 0) {
		if (pINTData->byISR0 & ISR_BNTX) {
			if (pDevice->eOPMode == OP_MODE_AP) {
				if (pMgmt->byDTIMCount > 0) {
					pMgmt->byDTIMCount--;
					pMgmt->sNodeDBTable[0].bRxPSPoll =
						FALSE;
				} else if (pMgmt->byDTIMCount == 0) {
					/* check if mutltcast tx bufferring */
					pMgmt->byDTIMCount =
						pMgmt->byDTIMPeriod-1;
					pMgmt->sNodeDBTable[0].bRxPSPoll = TRUE;
					if (pMgmt->sNodeDBTable[0].bPSEnable)
						bScheduleCommand((void *) pDevice,
								 WLAN_CMD_RX_PSPOLL,
								 NULL);
				}
				bScheduleCommand((void *) pDevice,
						WLAN_CMD_BECON_SEND,
						NULL);
			} /* if (pDevice->eOPMode == OP_MODE_AP) */
		pDevice->bBeaconSent = TRUE;
		} else {
			pDevice->bBeaconSent = FALSE;
		}
		if (pINTData->byISR0 & ISR_TBTT) {
			if (pDevice->bEnablePSMode)
				bScheduleCommand((void *) pDevice,
						WLAN_CMD_TBTT_WAKEUP,
						NULL);
			if (pDevice->bChannelSwitch) {
				pDevice->byChannelSwitchCount--;
				if (pDevice->byChannelSwitchCount == 0)
					bScheduleCommand((void *) pDevice,
							WLAN_CMD_11H_CHSW,
							NULL);
			}
		}
		LODWORD(pDevice->qwCurrTSF) = pINTData->dwLoTSF;
		HIDWORD(pDevice->qwCurrTSF) = pINTData->dwHiTSF;
		/*DBG_PRN_GRP01(("ISR0 = %02x ,
		  LoTsf =  %08x,
		  HiTsf =  %08x\n",
		  pINTData->byISR0,
		  pINTData->dwLoTSF,
		  pINTData->dwHiTSF)); */

		STAvUpdate802_11Counter(&pDevice->s802_11Counter,
					&pDevice->scStatistic,
					pINTData->byRTSSuccess,
					pINTData->byRTSFail,
					pINTData->byACKFail,
					pINTData->byFCSErr);
		STAvUpdateIsrStatCounter(&pDevice->scStatistic,
					pINTData->byISR0,
					pINTData->byISR1);
	}
	if (pINTData->byISR1 != 0)
		if (pINTData->byISR1 & ISR_GPIO3)
			bScheduleCommand((void *) pDevice,
					WLAN_CMD_RADIO,
					NULL);
	pDevice->intBuf.uDataLen = 0;
	pDevice->intBuf.bInUse = FALSE;

	pStats->tx_packets = pDevice->scStatistic.ullTsrOK;
	pStats->tx_bytes = pDevice->scStatistic.ullTxDirectedBytes +
		pDevice->scStatistic.ullTxMulticastBytes +
		pDevice->scStatistic.ullTxBroadcastBytes;
	pStats->tx_errors = pDevice->scStatistic.dwTsrErr;
	pStats->tx_dropped = pDevice->scStatistic.dwTsrErr;
}
