/*
 * 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_DEBUG;
static int          msglevel                =MSG_LEVEL_INFO;


/*---------------------  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(
    PVOID Context
    )
{
    PSDevice pDevice = (PSDevice) Context;
    NTSTATUS 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);

 }


NTSTATUS
INTnsProcessData(
    IN  PSDevice pDevice
    )
{
    NTSTATUS        status = STATUS_SUCCESS;
    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((HANDLE)pDevice, WLAN_CMD_RX_PSPOLL, NULL);
                    }
                }
                bScheduleCommand((HANDLE)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((HANDLE) pDevice, WLAN_CMD_TBTT_WAKEUP, NULL);
            }
            if ( pDevice->bChannelSwitch ) {
                pDevice->byChannelSwitchCount--;
                if ( pDevice->byChannelSwitchCount == 0 ) {
                    bScheduleCommand((HANDLE) 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((HANDLE) 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;

    return status;
}
