/*
 * rx.c
 *
 * Copyright(c) 1998 - 2010 Texas Instruments. All rights reserved.      
 * All rights reserved.                                                  
 *                                                                       
 * Redistribution and use in source and binary forms, with or without    
 * modification, are permitted provided that the following conditions    
 * are met:                                                              
 *                                                                       
 *  * Redistributions of source code must retain the above copyright     
 *    notice, this list of conditions and the following disclaimer.      
 *  * Redistributions in binary form must reproduce the above copyright  
 *    notice, this list of conditions and the following disclaimer in    
 *    the documentation and/or other materials provided with the         
 *    distribution.                                                      
 *  * Neither the name Texas Instruments nor the names of its            
 *    contributors may be used to endorse or promote products derived    
 *    from this software without specific prior written permission.      
 *                                                                       
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/***************************************************************************/
/*                                                                         */
/*      MODULE: Rx.c                                                       */
/*    PURPOSE:  Rx module functions                                        */
/*                                                                         */
/***************************************************************************/
#define __FILE_ID__  FILE_ID_54
#include "tidef.h"
#include "paramOut.h"
#include "rx.h"
#include "osApi.h"
#include "timer.h"
#include "DataCtrl_Api.h"
#include "Ctrl.h"
#include "802_11Defs.h"
#include "Ethernet.h"
#include "report.h"
#include "rate.h"
#include "mlmeApi.h"
#include "rsnApi.h"
#include "smeApi.h"
#include "siteMgrApi.h"
#include "GeneralUtil.h"
#include "EvHandler.h"
#ifdef XCC_MODULE_INCLUDED
#include "XCCMngr.h"
#endif
#include "TWDriver.h"
#include "RxBuf.h"
#include "DrvMainModules.h"
#include "bmtrace_api.h"
#include "PowerMgr_API.h"


#define EAPOL_PACKET                    0x888E
#define IAPP_PACKET                     0x0000
#define PREAUTH_EAPOL_PACKET            0x88C7


#define RX_DATA_FILTER_FLAG_NO_BIT_MASK         0
#define RX_DATA_FILTER_FLAG_USE_BIT_MASK        1
#define RX_DATA_FILTER_FLAG_IP_HEADER           0
#define RX_DATA_FILTER_FLAG_ETHERNET_HEADER     2
#define RX_DATA_FILTER_ETHERNET_HEADER_BOUNDARY 14

#define PADDING_ETH_PACKET_SIZE                 2

/* CallBack for recieving packet from rxXfer */
static void rxData_ReceivePacket (TI_HANDLE   hRxData,  void  *pBuffer);

static ERxBufferStatus rxData_RequestForBuffer (TI_HANDLE   hRxData, void **pBuf, TI_UINT16 aLength, TI_UINT32 uEncryptionFlag,PacketClassTag_e ePacketClassTag);

#if 0
static TI_STATUS rxData_checkBssIdAndBssType(TI_HANDLE hRxData, 
											 dot11_header_t* dot11_header,
											 TMacAddr **rxBssid, 
											 ScanBssType_e  *currBssType,
											 TMacAddr  *currBssId);
#endif
static TI_STATUS rxData_convertWlanToEthHeader (TI_HANDLE hRxData, void *pBuffer, TI_UINT16 * etherType);
static TI_STATUS rxData_ConvertAmsduToEthPackets (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr);
static void rxData_dataPacketDisptcher (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr);
static void rxData_discardPacket (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr);
static void rxData_discardPacketVlan (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr);
static void rxData_rcvPacketInOpenNotify (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr);
static void rxData_rcvPacketEapol (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr);
static void rxData_rcvPacketData (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr);

static TI_STATUS rxData_enableDisableRxDataFilters(TI_HANDLE hRxData, TI_BOOL enabled);
static TI_STATUS rxData_addRxDataFilter(TI_HANDLE hRxData, TRxDataFilterRequest* request);
static TI_STATUS rxData_removeRxDataFilter(TI_HANDLE hRxData, TRxDataFilterRequest* request);


#ifdef XCC_MODULE_INCLUDED
static void rxData_rcvPacketIapp(TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr);
#endif
#ifdef TI_DBG
static void rxData_printRxThroughput(TI_HANDLE hRxData, TI_BOOL bTwdInitOccured);
#endif

static void rxData_StartReAuthActiveTimer(TI_HANDLE hRxData);
static void reAuthTimeout(TI_HANDLE hRxData, TI_BOOL bTwdInitOccured);
static void rxData_ReauthEnablePriority(TI_HANDLE hRxData);


/*************************************************************************
*                        rxData_create                                   *
**************************************************************************
* DESCRIPTION:  This function initializes the Rx data module.                 
*                                                      
* INPUT:        hOs - handle to Os Abstraction Layer
*
* OUTPUT:      
*
* RETURN:       Handle to the allocated Rx data control block
************************************************************************/
TI_HANDLE rxData_create (TI_HANDLE hOs)
{
    rxData_t *pRxData;

    /* check parameters validity */
    if (hOs == NULL)
    {
        WLAN_OS_REPORT(("FATAL ERROR: rxData_create(): OS handle Error - Aborting\n"));
        return NULL;
    }
    

    /* alocate Rx module control block */
    pRxData = os_memoryAlloc(hOs, (sizeof(rxData_t)));

    if (!pRxData)
    {
        WLAN_OS_REPORT(("FATAL ERROR: rxData_create(): Error Creating Rx Module - Aborting\n"));
        return NULL;
    }

    /* reset Rx control block */
    os_memoryZero (hOs, pRxData, (sizeof(rxData_t)));

    pRxData->RxEventDistributor = DistributorMgr_Create (hOs, MAX_RX_NOTIF_REQ_ELMENTS);

    pRxData->hOs = hOs;

    return (TI_HANDLE)pRxData;
}

/***************************************************************************
*                           rxData_config                                  *
****************************************************************************
* DESCRIPTION:  This function configures the Rx Data module     
* 
* INPUTS:       pStadHandles  - The driver modules handles
*
* OUTPUT:       
* 
* RETURNS:      void
***************************************************************************/
void rxData_init (TStadHandlesList *pStadHandles)
{
    rxData_t *pRxData = (rxData_t *)(pStadHandles->hRxData);

    pRxData->hCtrlData  = pStadHandles->hCtrlData; 
    pRxData->hTWD       = pStadHandles->hTWD;
    pRxData->hMlme      = pStadHandles->hMlmeSm; 
    pRxData->hRsn       = pStadHandles->hRsn;
    pRxData->hSiteMgr   = pStadHandles->hSiteMgr;
    pRxData->hOs        = pStadHandles->hOs;
    pRxData->hReport    = pStadHandles->hReport;
    pRxData->hXCCMgr    = pStadHandles->hXCCMngr;
    pRxData->hEvHandler = pStadHandles->hEvHandler;
    pRxData->hTimer     = pStadHandles->hTimer;
    pRxData->hPowerMgr  = pStadHandles->hPowerMgr;

    pRxData->rxDataExcludeUnencrypted = DEF_EXCLUDE_UNENCYPTED; 
    pRxData->rxDataExludeBroadcastUnencrypted = DEF_EXCLUDE_UNENCYPTED;
    pRxData->rxDataEapolDestination = DEF_EAPOL_DESTINATION;
    pRxData->rxDataPortStatus = DEF_RX_PORT_STATUS;
	pRxData->genericEthertype = EAPOL_PACKET;

    /*
     * configure rx data dispatcher 
     */

    /* port status close */
    pRxData->rxData_dispatchBuffer[CLOSE][DATA_DATA_PACKET]  = &rxData_discardPacket;       /* data  */
    pRxData->rxData_dispatchBuffer[CLOSE][DATA_EAPOL_PACKET] = &rxData_discardPacket;       /* eapol */
    pRxData->rxData_dispatchBuffer[CLOSE][DATA_IAPP_PACKET]  = &rxData_discardPacket;       /* Iapp  */
    pRxData->rxData_dispatchBuffer[CLOSE][DATA_VLAN_PACKET]  = &rxData_discardPacketVlan;   /* VLAN  */

    /* port status open notify */
    pRxData->rxData_dispatchBuffer[OPEN_NOTIFY][DATA_DATA_PACKET]  = &rxData_rcvPacketInOpenNotify; /* data  */ 
    pRxData->rxData_dispatchBuffer[OPEN_NOTIFY][DATA_EAPOL_PACKET] = &rxData_rcvPacketInOpenNotify; /* eapol */ 
    pRxData->rxData_dispatchBuffer[OPEN_NOTIFY][DATA_IAPP_PACKET]  = &rxData_rcvPacketInOpenNotify; /* Iapp  */ 
    pRxData->rxData_dispatchBuffer[OPEN_NOTIFY][DATA_VLAN_PACKET]  = &rxData_discardPacketVlan;     /* VLAN  */

    /* port status open eapol */
    pRxData->rxData_dispatchBuffer[OPEN_EAPOL][DATA_DATA_PACKET]  = &rxData_discardPacket;      /* data  */ 
    pRxData->rxData_dispatchBuffer[OPEN_EAPOL][DATA_EAPOL_PACKET] = &rxData_rcvPacketEapol;     /* eapol */ 
    pRxData->rxData_dispatchBuffer[OPEN_EAPOL][DATA_IAPP_PACKET]  = &rxData_discardPacket;      /* Iapp  */ 
    pRxData->rxData_dispatchBuffer[OPEN_EAPOL][DATA_VLAN_PACKET]  = &rxData_discardPacketVlan;  /* VLAN  */

    /* port status open */
    pRxData->rxData_dispatchBuffer[OPEN][DATA_DATA_PACKET]  = &rxData_rcvPacketData;    /* data  */ 
    pRxData->rxData_dispatchBuffer[OPEN][DATA_EAPOL_PACKET] = &rxData_rcvPacketEapol;   /* eapol */ 
#ifdef XCC_MODULE_INCLUDED
    pRxData->rxData_dispatchBuffer[OPEN][DATA_IAPP_PACKET]  = &rxData_rcvPacketIapp;    /* Iapp  */ 
#else
    pRxData->rxData_dispatchBuffer[OPEN][DATA_IAPP_PACKET]  = &rxData_rcvPacketData;    /* Iapp  */ 
#endif
    pRxData->rxData_dispatchBuffer[OPEN][DATA_VLAN_PACKET]  = &rxData_discardPacketVlan;/* VLAN  */

    /* register CB's for request buffer and receive CB to the lower layers */
    TWD_RegisterCb (pRxData->hTWD,
                    TWD_EVENT_RX_RECEIVE_PACKET,
                    (void *)rxData_ReceivePacket, 
                    pStadHandles->hRxData);

    TWD_RegisterCb (pRxData->hTWD,
                    TWD_EVENT_RX_REQUEST_FOR_BUFFER,
                    (void*)rxData_RequestForBuffer, 
                    pStadHandles->hRxData);
}


TI_STATUS rxData_SetDefaults (TI_HANDLE hRxData, rxDataInitParams_t * rxDataInitParams)
{
    rxData_t *pRxData = (rxData_t *)hRxData;
    int i;

    /* init rx data filters */
    pRxData->filteringEnabled = rxDataInitParams->rxDataFiltersEnabled;
    pRxData->filteringDefaultAction = rxDataInitParams->rxDataFiltersDefaultAction;
    TWD_CfgEnableRxDataFilter (pRxData->hTWD, pRxData->filteringEnabled, pRxData->filteringDefaultAction);

    for (i = 0; i < MAX_DATA_FILTERS; ++i)
    {
        if (rxDataInitParams->rxDataFilterRequests[i].maskLength > 0)
        {
            if (rxData_addRxDataFilter(hRxData, &rxDataInitParams->rxDataFilterRequests[i]) != TI_OK)
            {
                TRACE1(pRxData->hReport, REPORT_SEVERITY_ERROR, ": Invalid Rx Data Filter configured at init stage (at index %d)!\n", i);
            }
        }
    }

	pRxData->reAuthActiveTimer = tmr_CreateTimer (pRxData->hTimer);
	if (pRxData->reAuthActiveTimer == NULL)
	{
        WLAN_OS_REPORT(("rxData_SetDefaults(): Failed to create reAuthActiveTimer!\n"));
		return TI_NOK;
	}

    pRxData->reAuthActiveTimeout = rxDataInitParams->reAuthActiveTimeout;

	rxData_SetReAuthInProgress(pRxData, TI_FALSE);

#ifdef TI_DBG
    /* reset counters */
    rxData_resetCounters(pRxData);
    rxData_resetDbgCounters(pRxData);

    /* allocate timer for debug throughput */
    pRxData->hThroughputTimer = tmr_CreateTimer (pRxData->hTimer);
    if (pRxData->hThroughputTimer == NULL)
    {
        TRACE0(pRxData->hReport, REPORT_SEVERITY_ERROR, "rxData_SetDefaults(): Failed to create hThroughputTimer!\n");
        return TI_NOK;
    }
    pRxData->rxThroughputTimerEnable = TI_FALSE;
#endif


    TRACE0(pRxData->hReport, REPORT_SEVERITY_INIT, ".....Rx Data configured successfully\n");

    return TI_OK;
}

/***************************************************************************
*                           rxData_unLoad                                  *
****************************************************************************
* DESCRIPTION:  This function unload the Rx data module. 
* 
* INPUTS:       hRxData - the object
*       
* OUTPUT:       
* 
* RETURNS:      TI_OK - Unload succesfull
*               TI_NOK - Unload unsuccesfull
***************************************************************************/
TI_STATUS rxData_unLoad(TI_HANDLE hRxData)
{
    rxData_t *pRxData = (rxData_t *)hRxData;

    /* check parameters validity */
    if (pRxData == NULL)
    {
        return TI_NOK;
    }

    DistributorMgr_Destroy(pRxData->RxEventDistributor);

#ifdef TI_DBG
    /* destroy periodic rx throughput timer */
	if (pRxData->hThroughputTimer)
	{
		tmr_DestroyTimer (pRxData->hThroughputTimer);
	}
  #endif

	if (pRxData->reAuthActiveTimer)
	{
		tmr_DestroyTimer (pRxData->reAuthActiveTimer);
	}

    /* free Rx Data controll block */
    os_memoryFree(pRxData->hOs, pRxData, sizeof(rxData_t));

    return TI_OK;
}


/***************************************************************************
*                           rxData_stop                                    *
****************************************************************************
* DESCRIPTION:  this function stop the rx data. 
* 
* INPUTS:       hRxData - the object
*       
* OUTPUT:       
* 
* RETURNS:      TI_OK - stop succesfull
*               TI_NOK - stop unsuccesfull
***************************************************************************/
TI_STATUS rxData_stop (TI_HANDLE hRxData)
{
    rxData_t *pRxData = (rxData_t *)hRxData;

    /* check parameters validity */
    if (pRxData == NULL)
    {
        return TI_NOK;
    }

    pRxData->rxDataExcludeUnencrypted = DEF_EXCLUDE_UNENCYPTED; 
    pRxData->rxDataExludeBroadcastUnencrypted = DEF_EXCLUDE_UNENCYPTED;
    pRxData->rxDataEapolDestination = DEF_EAPOL_DESTINATION;
    pRxData->rxDataPortStatus = DEF_RX_PORT_STATUS;

  #ifdef TI_DBG
    /* reset counters */
    /*rxData_resetCounters(pRxData);*/
    /*rxData_resetDbgCounters(pRxData);*/

    /* stop throughput timer */
    if (pRxData->rxThroughputTimerEnable)
    {
        tmr_StopTimer (pRxData->hThroughputTimer);
        pRxData->rxThroughputTimerEnable = TI_FALSE;
    }
  #endif

    TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_stop() :  Succeeded.\n");

    return TI_OK;

}

/***************************************************************************
*                           rxData_getParam                                *
****************************************************************************
* DESCRIPTION:  get a specific parameter
* 
* INPUTS:       hRxData - the object
*               
* OUTPUT:       pParamInfo - structure which include the value of 
*               the requested parameter
* 
* RETURNS:      TI_OK
*               TI_NOK
***************************************************************************/
TI_STATUS rxData_getParam(TI_HANDLE hRxData, paramInfo_t *pParamInfo)
{
    rxData_t *pRxData = (rxData_t *)hRxData;

    /* check handle validity */
    if (pRxData == NULL)
    {
        return TI_NOK;
    }

    switch (pParamInfo->paramType)
    {
        case RX_DATA_EXCLUDE_UNENCRYPTED_PARAM:
            pParamInfo->content.rxDataExcludeUnencrypted = pRxData->rxDataExcludeUnencrypted;
            break;

        case RX_DATA_EAPOL_DESTINATION_PARAM:
            pParamInfo->content.rxDataEapolDestination = pRxData->rxDataEapolDestination;
            break;

        case RX_DATA_PORT_STATUS_PARAM:
            pParamInfo->content.rxDataPortStatus = pRxData->rxDataPortStatus;
            break;

        case RX_DATA_COUNTERS_PARAM:
            pParamInfo->content.siteMgrTiWlanCounters.RecvOk = pRxData->rxDataCounters.RecvOk;              
            pParamInfo->content.siteMgrTiWlanCounters.DirectedBytesRecv = pRxData->rxDataCounters.DirectedBytesRecv;        
            pParamInfo->content.siteMgrTiWlanCounters.DirectedFramesRecv = pRxData->rxDataCounters.DirectedFramesRecv;      
            pParamInfo->content.siteMgrTiWlanCounters.MulticastBytesRecv = pRxData->rxDataCounters.MulticastBytesRecv;      
            pParamInfo->content.siteMgrTiWlanCounters.MulticastFramesRecv = pRxData->rxDataCounters.MulticastFramesRecv;    
            pParamInfo->content.siteMgrTiWlanCounters.BroadcastBytesRecv = pRxData->rxDataCounters.BroadcastBytesRecv;      
            pParamInfo->content.siteMgrTiWlanCounters.BroadcastFramesRecv = pRxData->rxDataCounters.BroadcastFramesRecv;    
            break;

        case RX_DATA_GET_RX_DATA_FILTERS_STATISTICS:
            TWD_ItrDataFilterStatistics (pRxData->hTWD, 
                                         pParamInfo->content.interogateCmdCBParams.fCb,
                                         pParamInfo->content.interogateCmdCBParams.hCb, 
                                         pParamInfo->content.interogateCmdCBParams.pCb);
            break;

        case RX_DATA_RATE_PARAM:
            pParamInfo->content.siteMgrCurrentRxRate = pRxData->uLastDataPktRate;
            break;

        default:
            TRACE0(pRxData->hReport, REPORT_SEVERITY_ERROR, " rxData_getParam() : PARAMETER NOT SUPPORTED \n");
            return (PARAM_NOT_SUPPORTED);
    }

    return TI_OK;
}

/***************************************************************************
*                           rxData_setParam                                *
****************************************************************************
* DESCRIPTION:  set a specific parameter
* 
* INPUTS:       hRxData - the object
*               pParamInfo - structure which include the value to set for 
*               the requested parameter
*       
* OUTPUT:       
* 
* RETURNS:      TI_OK
*               TI_NOK
***************************************************************************/
TI_STATUS rxData_setParam(TI_HANDLE hRxData, paramInfo_t *pParamInfo)
{
    rxData_t *pRxData = (rxData_t *)hRxData;

    /* check handle validity */
    if( pRxData == NULL  )
    {
        return TI_NOK;
    }

    switch (pParamInfo->paramType)
    {
        case RX_DATA_EXCLUDE_UNENCRYPTED_PARAM:
            pRxData->rxDataExcludeUnencrypted = pParamInfo->content.rxDataExcludeUnencrypted;
            break;
        case RX_DATA_EXCLUDE_BROADCAST_UNENCRYPTED_PARAM:
            pRxData->rxDataExludeBroadcastUnencrypted = pParamInfo->content.rxDataExcludeUnencrypted;
            break;
        case RX_DATA_EAPOL_DESTINATION_PARAM:
            pRxData->rxDataEapolDestination = pParamInfo->content.rxDataEapolDestination;
            break;

        case RX_DATA_PORT_STATUS_PARAM:
            pRxData->rxDataPortStatus = pParamInfo->content.rxDataPortStatus;
            break;

        case RX_DATA_ENABLE_DISABLE_RX_DATA_FILTERS:
            return rxData_enableDisableRxDataFilters(hRxData, pParamInfo->content.rxDataFilterEnableDisable);

        case RX_DATA_ADD_RX_DATA_FILTER:
        {
            TRxDataFilterRequest* pRequest = &pParamInfo->content.rxDataFilterRequest;            

            return rxData_addRxDataFilter(hRxData, pRequest);
        }

        case RX_DATA_REMOVE_RX_DATA_FILTER:
        {
            TRxDataFilterRequest* pRequest = &pParamInfo->content.rxDataFilterRequest;
            
            return rxData_removeRxDataFilter(hRxData, pRequest);
        }

        case RX_DATA_GENERIC_ETHERTYPE_PARAM:
            pRxData->genericEthertype = pParamInfo->content.rxGenericEthertype;
            break;

        default:
            TRACE0(pRxData->hReport, REPORT_SEVERITY_ERROR, " rxData_setParam() : PARAMETER NOT SUPPORTED \n");
            return (PARAM_NOT_SUPPORTED);
    }

    return TI_OK;
}

/***************************************************************************
*                     rxData_enableDisableRxDataFilters                    *
****************************************************************************
* DESCRIPTION:  
*               
* 
* INPUTS:       
*               
*               
*       
* OUTPUT:       
* 
* RETURNS:      
*               
***************************************************************************/
static TI_STATUS rxData_enableDisableRxDataFilters(TI_HANDLE hRxData, TI_BOOL enabled)
{
    rxData_t * pRxData = (rxData_t *) hRxData;

    /* assert 0 or 1 */
    if (enabled != TI_FALSE)
        enabled = 1;

    if (enabled == pRxData->filteringEnabled)
        return TI_OK;

    pRxData->filteringEnabled = enabled;

    return TWD_CfgEnableRxDataFilter (pRxData->hTWD, pRxData->filteringEnabled, pRxData->filteringDefaultAction);
}

/***************************************************************************
*                          findFilterRequest                               *
****************************************************************************
* DESCRIPTION:  
*               
* 
* INPUTS:       
*               
*               
*       
* OUTPUT:       
* 
* RETURNS:      
*               
***************************************************************************/
static int findFilterRequest(TI_HANDLE hRxData, TRxDataFilterRequest* request)
{
    rxData_t * pRxData = (rxData_t *) hRxData;
    int i;
    
    for (i = 0; i < MAX_DATA_FILTERS; ++i)
    {
        if (pRxData->isFilterSet[i])
        {
            if ((pRxData->filterRequests[i].offset == request->offset) &&
                (pRxData->filterRequests[i].maskLength == request->maskLength) &&
                (pRxData->filterRequests[i].patternLength == request->patternLength))
            {
                if ((os_memoryCompare(pRxData->hOs, pRxData->filterRequests[i].mask, request->mask, request->maskLength) == 0) &&
                    (os_memoryCompare(pRxData->hOs, pRxData->filterRequests[i].pattern, request->pattern, request->patternLength) == 0))
                    return i;
            }
        }
    }

    return -1;
}

/***************************************************************************
*                            closeFieldPattern                             *
****************************************************************************
* DESCRIPTION:  
*               
* 
* INPUTS:       
*               
*               
*       
* OUTPUT:       
* 
* RETURNS:      
*               
***************************************************************************/
static void closeFieldPattern (rxData_t * pRxData, rxDataFilterFieldPattern_t * fieldPattern, TI_UINT8 * fieldPatterns, TI_UINT8 * lenFieldPatterns)
{
    //fieldPatterns[*lenFieldPatterns] = fieldPattern->offset;
	os_memoryCopy(pRxData->hOs, fieldPatterns + *lenFieldPatterns, (TI_UINT8 *)&fieldPattern->offset, sizeof(fieldPattern->offset));
    *lenFieldPatterns += sizeof(fieldPattern->offset);

    fieldPatterns[*lenFieldPatterns] = fieldPattern->length;
    *lenFieldPatterns += sizeof(fieldPattern->length);

    fieldPatterns[*lenFieldPatterns] = fieldPattern->flag;
    *lenFieldPatterns += sizeof(fieldPattern->flag);

    os_memoryCopy(pRxData->hOs, fieldPatterns + *lenFieldPatterns, fieldPattern->pattern, fieldPattern->length);
    *lenFieldPatterns += fieldPattern->length;

    /* if the pattern bit mask is enabled add it to the end of the request */
    if ((fieldPattern->flag & RX_DATA_FILTER_FLAG_USE_BIT_MASK) == RX_DATA_FILTER_FLAG_USE_BIT_MASK)
    {
        os_memoryCopy(pRxData->hOs, fieldPatterns + *lenFieldPatterns, fieldPattern->mask, fieldPattern->length);
        *lenFieldPatterns += fieldPattern->length;
    }

    TRACE3(pRxData->hReport, REPORT_SEVERITY_INFORMATION, ": Closed field pattern, length = %d, total length = %d, pattern bit mask = %d.\n", fieldPattern->length, *lenFieldPatterns, ((fieldPattern->flag & RX_DATA_FILTER_FLAG_USE_BIT_MASK) == RX_DATA_FILTER_FLAG_USE_BIT_MASK));
}


/***************************************************************************
*                         parseRxDataFilterRequest                         *
****************************************************************************
* DESCRIPTION:  
*               
* 
* INPUTS:       
*               
*               
*       
* OUTPUT:       
* 
* RETURNS:      
*               
***************************************************************************/
static int parseRxDataFilterRequest(TI_HANDLE hRxData, TRxDataFilterRequest* request, TI_UINT8 * numFieldPatterns, TI_UINT8 * lenFieldPatterns, TI_UINT8 * fieldPatterns)
{
    rxData_t * pRxData = (rxData_t *) hRxData;

    int maskIter;
    int patternIter = 0;

    /* used to store field patterns while they are built */
    TI_BOOL isBuildingFieldPattern = TI_FALSE;
    rxDataFilterFieldPattern_t fieldPattern;

    for (maskIter = 0; maskIter < request->maskLength * 8; ++maskIter)
    {
        /* which byte in the mask and which bit in the byte we're at */
        int bit = maskIter % 8;
        int byte = maskIter / 8;

        /* is the bit in the mask set */
        TI_BOOL isSet = ((request->mask[byte] & (1 << bit)) == (1 << bit));

        TRACE4(pRxData->hReport, REPORT_SEVERITY_INFORMATION, ": MaskIter = %d, Byte = %d, Bit = %d, isSet = %d\n", maskIter, byte, bit, isSet);

        /* if we're in the midst of building a field pattern, we need to close in case */
        /* the current bit is not set or we've reached the ethernet header boundary */
        if (isBuildingFieldPattern)
        {
            if ((isSet == TI_FALSE) || (request->offset + maskIter == RX_DATA_FILTER_ETHERNET_HEADER_BOUNDARY))
            {
                closeFieldPattern(hRxData, &fieldPattern, fieldPatterns, lenFieldPatterns);

                isBuildingFieldPattern = TI_FALSE;
            }
        }

        /* nothing to do in case the bit is not set */
        if (isSet)
        {
            /* if not already building a field pattern, create a new one */
            if (isBuildingFieldPattern == TI_FALSE)
            {
                TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, ": Creating a new field pattern.\n");

                isBuildingFieldPattern = TI_TRUE;
                ++(*numFieldPatterns);

                if (*numFieldPatterns > RX_DATA_FILTER_MAX_FIELD_PATTERNS)
                {
                    TRACE1(pRxData->hReport, REPORT_SEVERITY_ERROR, ": Invalid filter, too many field patterns, maximum of %u is allowed!\n", RX_DATA_FILTER_MAX_FIELD_PATTERNS);

                    return TI_NOK;
                }

                fieldPattern.offset = request->offset + maskIter;
                fieldPattern.length = 0;

                /* we don't support the mask per bit feature yet. */
                fieldPattern.flag = RX_DATA_FILTER_FLAG_NO_BIT_MASK;

                /* first 14 bits are used for the Ethernet header, rest for the IP header */
                if (fieldPattern.offset < RX_DATA_FILTER_ETHERNET_HEADER_BOUNDARY)
                {
                    fieldPattern.flag |= RX_DATA_FILTER_FLAG_ETHERNET_HEADER;
                }
                else
                {
                    fieldPattern.flag |= RX_DATA_FILTER_FLAG_IP_HEADER;
                    fieldPattern.offset -= RX_DATA_FILTER_ETHERNET_HEADER_BOUNDARY;
                }

                TRACE2(pRxData->hReport, REPORT_SEVERITY_INFORMATION, ": offset = %d, flag = %d.\n", fieldPattern.offset, fieldPattern.flag);
            }

            /* check that the pattern is long enough */
            if (patternIter > request->patternLength)
            {
                TRACE0(pRxData->hReport, REPORT_SEVERITY_ERROR, ": Invalid filter, mask and pattern length are not consistent!\n");

                return TI_NOK;
            }

            /* add the current pattern byte to the field pattern */
            fieldPattern.pattern[fieldPattern.length++] = request->pattern[patternIter++];

            /* check pattern matching boundary */
            if (fieldPattern.offset + fieldPattern.length >= RX_DATA_FILTER_FILTER_BOUNDARY)
            {
                TRACE1(pRxData->hReport, REPORT_SEVERITY_ERROR, ": Invalid filter, pattern matching cannot exceed first %u characters.\n", RX_DATA_FILTER_FILTER_BOUNDARY);

                return TI_NOK;
            }
        }
    }

    /* check that the pattern is long enough */
    if (patternIter != request->patternLength)
    {
        TRACE0(pRxData->hReport, REPORT_SEVERITY_ERROR, ": Invalid filter, mask and pattern lengths are not consistent!\n");

        return TI_NOK;
    }

    /* close the last field pattern if needed */
    if (isBuildingFieldPattern)
    {
        closeFieldPattern (hRxData, &fieldPattern, fieldPatterns, lenFieldPatterns);
    }

    return TI_OK;
}


/***************************************************************************
*                           rxData_setRxDataFilter                         *
****************************************************************************
* DESCRIPTION:  
*               
* 
* INPUTS:       
*               
*               
*       
* OUTPUT:       
* 
* RETURNS:      
*               
***************************************************************************/
static TI_STATUS rxData_addRxDataFilter (TI_HANDLE hRxData, TRxDataFilterRequest* request)
{
    rxData_t * pRxData = (rxData_t *) hRxData;

    /* firmware request fields */
    TI_UINT8 index = 0;
    TI_UINT8 numFieldPatterns = 0;
    TI_UINT8 lenFieldPatterns = 0;
    TI_UINT8 fieldPatterns[MAX_DATA_FILTER_SIZE];

    /* does the filter already exist? */
    if (findFilterRequest(hRxData, request) >= 0)
    {
        TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, ": Filter already exists.\n");

        return RX_FILTER_ALREADY_EXISTS;
    }

    /* find place for insertion */
    for (index = 0; index < MAX_DATA_FILTERS; ++index)
    {
        if (pRxData->isFilterSet[index] == TI_FALSE)
            break;
    }

    /* are all filter slots taken? */
    if (index == MAX_DATA_FILTERS)
    {
        TRACE0(pRxData->hReport, REPORT_SEVERITY_ERROR, ": No place to insert filter!\n");

        return RX_NO_AVAILABLE_FILTERS;
    }

    TRACE1(pRxData->hReport, REPORT_SEVERITY_INFORMATION, ": Inserting filter at index %d.\n", index);

    /* parse the filter request into discrete field patterns */
    if (parseRxDataFilterRequest(hRxData, request, &numFieldPatterns, &lenFieldPatterns, fieldPatterns) != TI_OK)
        return TI_NOK;

    if (numFieldPatterns == 0)
        return TI_NOK;

    /* Store configuration for future manipulation */
    pRxData->isFilterSet[index] = TI_TRUE;
    os_memoryCopy(pRxData->hOs, &pRxData->filterRequests[index], request, sizeof(pRxData->filterRequests[index]));

    /* Send configuration to firmware */
    return TWD_CfgRxDataFilter (pRxData->hTWD, 
                                index, 
                                ADD_FILTER, 
                                FILTER_SIGNAL, 
                                numFieldPatterns, 
                                lenFieldPatterns, 
                                fieldPatterns);

}

/***************************************************************************
*                         rxData_removeRxDataFilter                        *
****************************************************************************
* DESCRIPTION:  
*               
* 
* INPUTS:       
*               
*               
*       
* OUTPUT:       
* 
* RETURNS:      
*               
***************************************************************************/
static TI_STATUS rxData_removeRxDataFilter (TI_HANDLE hRxData, TRxDataFilterRequest* request)
{
    rxData_t * pRxData = (rxData_t *) hRxData;

    int index = findFilterRequest(hRxData, request);

    /* does the filter exist? */
    if (index < 0)
    {
        TRACE0(pRxData->hReport, REPORT_SEVERITY_WARNING, ": Remove data filter request received but the specified filter was not found!");

        return RX_FILTER_DOES_NOT_EXIST;
    }

    TRACE1(pRxData->hReport, REPORT_SEVERITY_INFORMATION, ": Removing filter at index %d.", index);

    pRxData->isFilterSet[index] = TI_FALSE;

    return TWD_CfgRxDataFilter (pRxData->hTWD, 
                                index, 
                                REMOVE_FILTER, 
                                FILTER_SIGNAL, 
                                0, 
                                0, 
                                NULL);
}

/***************************************************************************
*                       rxData_DistributorRxEvent                          *
****************************************************************************
* DESCRIPTION:  
*               
* 
* INPUTS:       
*               
*               
*       
* OUTPUT:       
* 
* RETURNS:      
*               
***************************************************************************/
static void rxData_DistributorRxEvent (rxData_t *pRxData, TI_UINT16 Mask, int DataLen)
{
    DistributorMgr_EventCall (pRxData->RxEventDistributor, Mask, DataLen);
}

/***************************************************************************
*                       rxData_RegNotif                                    *
****************************************************************************/
TI_HANDLE rxData_RegNotif (TI_HANDLE hRxData, TI_UINT16 EventMask, GeneralEventCall_t CallBack, TI_HANDLE context, TI_UINT32 Cookie)
{
    rxData_t *pRxData = (rxData_t *)hRxData;

    if (!hRxData)
        return NULL;

    return DistributorMgr_Reg (pRxData->RxEventDistributor, EventMask, (TI_HANDLE)CallBack, context, Cookie);
}

/***************************************************************************
*                       rxData_AddToNotifMask                              *
****************************************************************************/
TI_STATUS rxData_AddToNotifMask (TI_HANDLE hRxData, TI_HANDLE Notifh, TI_UINT16 EventMask)
{
    rxData_t *pRxData = (rxData_t *)hRxData;

    if (!hRxData)
        return TI_NOK;

    return DistributorMgr_AddToMask (pRxData->RxEventDistributor, Notifh, EventMask);
}


/***************************************************************************
*                       rxData_UnRegNotif                                  *
****************************************************************************/
TI_STATUS rxData_UnRegNotif(TI_HANDLE hRxData,TI_HANDLE RegEventHandle)
{
    rxData_t *pRxData = (rxData_t *)hRxData;
    
    if (!hRxData)
        return TI_NOK;

    return DistributorMgr_UnReg (pRxData->RxEventDistributor, RegEventHandle);
}


/***************************************************************************
*                       rxData_receivePacketFromWlan                       *
****************************************************************************
* DESCRIPTION:  this function is called by the GWSI for each received Buffer.
*               It filter and distribute the received Buffer. 
* 
* INPUTS:       hRxData - the object
*               pBuffer - the received Buffer.
*               pRxAttr - Rx attributes
*       
* OUTPUT:       
* 
* RETURNS:      
***************************************************************************/
void rxData_receivePacketFromWlan (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr)
{
    rxData_t        *pRxData    = (rxData_t *)hRxData;
    TMacAddr        address3;
    dot11_header_t  *pDot11Hdr;

    TRACE1(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_receivePacketFromWlan() : pRxAttr->packetType = %d\n", pRxAttr->ePacketType);

    switch (pRxAttr->ePacketType)
    {
    case TAG_CLASS_MANAGEMENT:
    case TAG_CLASS_BCN_PRBRSP:

        TRACE1(pRxData->hReport, REPORT_SEVERITY_INFORMATION, "rxData_receivePacketFromWlan(): Received management Buffer len = %d\n", RX_BUF_LEN(pBuffer));

        /* update siteMngr 
         *
         * the BSSID in mgmt frames is always addr3 in the header 
         * must copy address3 since Buffer is freed in mlmeParser_recv
         */  
        pDot11Hdr = (dot11_header_t*)RX_BUF_DATA(pBuffer);
        
        os_memoryCopy(pRxData->hOs, &address3, &pDot11Hdr->address3, sizeof(address3));

        /* distribute mgmt pBuffer to mlme */
        if( mlmeParser_recv(pRxData->hMlme, pBuffer, pRxAttr) != TI_OK )
        {
            TRACE0(pRxData->hReport, REPORT_SEVERITY_ERROR, " rxData_receivePacketFromWlan() : MLME returned error \n");
        }
        break;

    case TAG_CLASS_DATA:
    case TAG_CLASS_QOS_DATA:
    case TAG_CLASS_AMSDU:
    case TAG_CLASS_EAPOL:
        {
            CL_TRACE_START_L3();
            TRACE1(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_receivePacketFromWlan() : Received Data Buffer len = %d\n", RX_BUF_LEN(pBuffer));

            /* send pBuffer to data dispatcher */
            rxData_dataPacketDisptcher(hRxData, pBuffer, pRxAttr);
            CL_TRACE_END_L3("tiwlan_drv.ko", "INHERIT", "RX", ".DataPacket");
            break;
        }

    default:
        TRACE0(pRxData->hReport, REPORT_SEVERITY_ERROR, " rxData_receivePacketFromWlan(): Received unspecified packet type !!! \n");
        RxBufFree(pRxData->hOs, pBuffer); 
        break;
    }
}

/***************************************************************************
*                       rxData_dataPacketDisptcher                         *
****************************************************************************
* DESCRIPTION:  this function is called upon receving data Buffer,
*               it dispatches the packet to the approciate function according to 
*               data packet type and rx port status. 
* 
* INPUTS:       hRxData - the object
*               pBuffer - the received Buffer.
*               pRxAttr - Rx attributes
*       
* OUTPUT:       
* 
* RETURNS:      
***************************************************************************/

static void rxData_dataPacketDisptcher (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr)
{
    rxData_t *pRxData = (rxData_t *)hRxData;
    portStatus_e DataPortStatus;
    rxDataPacketType_e DataPacketType;

    /* get rx port status */
    DataPortStatus = pRxData->rxDataPortStatus;

    /* discard data packets received while rx data port is closed */
    if (DataPortStatus == CLOSE)
    {
        TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_dataPacketDisptcher() : Received Data Buffer while Rx data port is closed \n");

        rxData_discardPacket (hRxData, pBuffer, pRxAttr);
        return;
    }

    /* get data packet type */

    pRxData->uLastDataPktRate = pRxAttr->Rate;  /* save Rx packet rate for statistics */

#ifdef XCC_MODULE_INCLUDED
    if (XCCMngr_isIappPacket (pRxData->hXCCMgr, pBuffer) == TI_TRUE)
    {
        TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_dataPacketDisptcher() : Received Iapp Buffer  \n");

        DataPacketType = DATA_IAPP_PACKET;

        /* dispatch Buffer according to packet type and current rx data port status */
        pRxData->rxData_dispatchBuffer[DataPortStatus][DataPacketType] (hRxData, pBuffer, pRxAttr);
    }
    else
#endif
    {
        /* A-MSDU ? */
        if (TAG_CLASS_AMSDU == pRxAttr->ePacketType)
        {
           rxData_ConvertAmsduToEthPackets (hRxData, pBuffer, pRxAttr);
        }
        else
        {
           TI_UINT16 etherType = 0;
           TEthernetHeader * pEthernetHeader;

           /*
            * if Host processes received packets, the header translation
            * from WLAN to ETH is done here. The conversion has been moved
            * here so that IAPP packets aren't converted.
            */
           rxData_convertWlanToEthHeader (hRxData, pBuffer, &etherType);

           pEthernetHeader = (TEthernetHeader *)RX_ETH_PKT_DATA(pBuffer);

           if (etherType == ETHERTYPE_802_1D)
           {
               TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_dataPacketDisptcher() : Received VLAN packet  \n");

               DataPacketType = DATA_VLAN_PACKET;
           }
           else if ((HTOWLANS(pEthernetHeader->type) == EAPOL_PACKET) ||
					(HTOWLANS(pEthernetHeader->type) == pRxData->genericEthertype))
           {
				TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_dataPacketDisptcher() : Received Eapol packet  \n");

				if (rxData_IsReAuthInProgress(pRxData))
				{
					/* ReAuth already in progress, restart timer */
					rxData_StopReAuthActiveTimer(pRxData);
					rxData_StartReAuthActiveTimer(pRxData);
				}
				else
				{
					if (PowerMgr_getReAuthActivePriority(pRxData->hPowerMgr))
					{
						/* ReAuth not in progress yet, force active, set flag, restart timer, send event */
						rxData_SetReAuthInProgress(pRxData, TI_TRUE);
						rxData_StartReAuthActiveTimer(pRxData);
						rxData_ReauthEnablePriority(pRxData);
						EvHandlerSendEvent(pRxData->hEvHandler, IPC_EVENT_RE_AUTH_STARTED, NULL, 0);
					}
				}

				DataPacketType = DATA_EAPOL_PACKET;
           }
           else
           {
               TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_dataPacketDisptcher() : Received Data packet  \n");

               DataPacketType = DATA_DATA_PACKET;
           }

           /* dispatch Buffer according to packet type and current rx data port status */
           pRxData->rxData_dispatchBuffer[DataPortStatus][DataPacketType] (hRxData, pBuffer, pRxAttr);
        }
    }

}

/***************************************************************************
*                       rxData_discardPacket                                   *
****************************************************************************
* DESCRIPTION:  this function is called to discard Buffer
* 
* INPUTS:       hRxData - the object
*               pBuffer - the received Buffer.
*               pRxAttr - Rx attributes
*       
* OUTPUT:       
* 
* RETURNS:      
***************************************************************************/
static void rxData_discardPacket (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr)
{
    rxData_t *pRxData = (rxData_t *)hRxData;

    TRACE2(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_discardPacket: rx port status = %d , Buffer status = %d  \n", pRxData->rxDataPortStatus, pRxAttr->status);

    pRxData->rxDataDbgCounters.excludedFrameCounter++;

    /* free Buffer */
    RxBufFree(pRxData->hOs, pBuffer); 

}

/***************************************************************************
*                       rxData_discardPacketVlan                                   *
****************************************************************************
* DESCRIPTION:  this function is called to discard Buffer
* 
* INPUTS:       hRxData - the object
*               pBuffer - the received Buffer.
*               pRxAttr - Rx attributes
*       
* OUTPUT:       
* 
* RETURNS:      
***************************************************************************/
static void rxData_discardPacketVlan (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr)
{
    rxData_t *pRxData = (rxData_t *)hRxData;

    TRACE0(pRxData->hReport, REPORT_SEVERITY_WARNING, " rxData_discardPacketVlan : drop packet that contains VLAN tag\n");

    pRxData->rxDataDbgCounters.rxDroppedDueToVLANIncludedCnt++;

    /* free Buffer */
    RxBufFree(pRxData->hOs, pBuffer); 
}


/***************************************************************************
*                       rxData_rcvPacketInOpenNotify                         *
****************************************************************************
* DESCRIPTION:  this function is called upon receving data Eapol packet type 
*               while rx port status is "open notify"
* 
* INPUTS:       hRxData - the object
*               pBuffer - the received Buffer.
*               pRxAttr - Rx attributes
*       
* OUTPUT:       
* 
* RETURNS:      
***************************************************************************/
static void rxData_rcvPacketInOpenNotify (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr)
{
    rxData_t *pRxData = (rxData_t *)hRxData;

    TRACE0(pRxData->hReport, REPORT_SEVERITY_ERROR, " rxData_rcvPacketInOpenNotify: receiving data packet while in rx port status is open notify\n");

    pRxData->rxDataDbgCounters.rcvUnicastFrameInOpenNotify++;

    /* free Buffer */
    RxBufFree(pRxData->hOs, pBuffer); 
}


/***************************************************************************
*                       rxData_rcvPacketEapol                               *
****************************************************************************
* DESCRIPTION:  this function is called upon receving data Eapol packet type 
*               while rx port status is "open  eapol"
* 
* INPUTS:       hRxData - the object
*               pBuffer - the received Buffer.
*               pRxAttr - Rx attributes
*       
* OUTPUT:       
* 
* RETURNS:      
***************************************************************************/
static void rxData_rcvPacketEapol(TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr)
{
    rxData_t *pRxData = (rxData_t *)hRxData;

    TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_rcvPacketEapol() : Received an EAPOL frame tranferred to OS\n");

    TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_rcvPacketEapol() : Received an EAPOL frame tranferred to OS\n");

    EvHandlerSendEvent (pRxData->hEvHandler, IPC_EVENT_EAPOL, NULL, 0);
    os_receivePacket (pRxData->hOs, (struct RxIfDescriptor_t*)pBuffer, pBuffer, (TI_UINT16)RX_ETH_PKT_LEN(pBuffer));

}

/***************************************************************************
*                       rxData_rcvPacketData                                 *
****************************************************************************
* DESCRIPTION:  this function is called upon receving data "data" packet type 
*               while rx port status is "open"
* 
* INPUTS:       hRxData - the object
*               pBuffer - the received Buffer.
*               pRxAttr - Rx attributes
*       
* OUTPUT:       
* 
* RETURNS:      
***************************************************************************/
static void rxData_rcvPacketData(TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr)
{
    rxData_t *pRxData = (rxData_t *)hRxData;
    TEthernetHeader *pEthernetHeader;
    TI_UINT16 EventMask = 0;
    TFwInfo *pFwInfo;

    TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_rcvPacketData() : Received DATA frame tranferred to OS\n");

    /* check encryption status */
    pEthernetHeader = (TEthernetHeader *)RX_ETH_PKT_DATA(pBuffer);
    if (!MAC_MULTICAST (pEthernetHeader->dst))
    {  /* unicast frame */
        if((pRxData->rxDataExcludeUnencrypted) && (!(pRxAttr->packetInfo & RX_DESC_ENCRYPT_MASK)))
        {
            pRxData->rxDataDbgCounters.excludedFrameCounter++;
            /* free Buffer */
            TRACE0(pRxData->hReport, REPORT_SEVERITY_WARNING, " rxData_rcvPacketData() : exclude unicast unencrypted is TI_TRUE & packet encryption is OFF\n");

            RxBufFree(pRxData->hOs, pBuffer);
            return;
        }
    }
    else
    {  /* broadcast frame */
        if ((pRxData->rxDataExludeBroadcastUnencrypted) && (!(pRxAttr->packetInfo & RX_DESC_ENCRYPT_MASK)))
        {
            pRxData->rxDataDbgCounters.excludedFrameCounter++;
            /* free Buffer */
            TRACE0(pRxData->hReport, REPORT_SEVERITY_WARNING, " rxData_rcvPacketData() : exclude broadcast unencrypted is TI_TRUE & packet encryption is OFF\n");

            RxBufFree(pRxData->hOs, pBuffer);
            return;
        }

        /*
         * Discard multicast/broadcast frames that we sent ourselves.
         * Per IEEE 802.11-2007 section 9.2.7: "STAs shall filter out
         * broadcast/multicast messages that contain their address as
         * the source address."
         */
        pFwInfo = TWD_GetFWInfo (pRxData->hTWD);
        if (MAC_EQUAL(pFwInfo->macAddress, pEthernetHeader->src))
        {
            pRxData->rxDataDbgCounters.excludedFrameCounter++;
            /* free Buffer */
            RxBufFree(pRxData->hOs, pBuffer);
            return;
        }
    }

    /* update traffic monitor parameters */
    pRxData->rxDataCounters.RecvOk++;
    EventMask |= RECV_OK;

    if (!MAC_MULTICAST (pEthernetHeader->dst)) 
    {
        /* Directed frame */
        pRxData->rxDataCounters.DirectedFramesRecv++;
        pRxData->rxDataCounters.DirectedBytesRecv += RX_ETH_PKT_LEN(pBuffer);
        EventMask |= DIRECTED_BYTES_RECV;  
        EventMask |= DIRECTED_FRAMES_RECV;
    }
    else if (MAC_BROADCAST (pEthernetHeader->dst)) 
    {
        /* Broadcast frame */
        pRxData->rxDataCounters.BroadcastFramesRecv++;
        pRxData->rxDataCounters.BroadcastBytesRecv += RX_ETH_PKT_LEN(pBuffer);
        EventMask |= BROADCAST_BYTES_RECV;  
        EventMask |= BROADCAST_FRAMES_RECV;
    }
    else 
    {
        /* Multicast Address */
        pRxData->rxDataCounters.MulticastFramesRecv++;
        pRxData->rxDataCounters.MulticastBytesRecv += RX_ETH_PKT_LEN(pBuffer);
        EventMask |= MULTICAST_BYTES_RECV;  
        EventMask |= MULTICAST_FRAMES_RECV;
    }
    pRxData->rxDataCounters.LastSecBytesRecv += RX_ETH_PKT_LEN(pBuffer);

    /*Handle PREAUTH_EAPOL_PACKET*/
    if (HTOWLANS(pEthernetHeader->type) == PREAUTH_EAPOL_PACKET)
    {
        TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_rcvPacketData() : Received an Pre-Auth EAPOL frame tranferred to OS\n");
    }

    rxData_DistributorRxEvent (pRxData, EventMask, RX_ETH_PKT_LEN(pBuffer));

    /* deliver packet to os */
    os_receivePacket (pRxData->hOs, (struct RxIfDescriptor_t*)pBuffer, pBuffer, (TI_UINT16)RX_ETH_PKT_LEN(pBuffer));
}


/***************************************************************************
*                       rxData_rcvPacketIapp                                 *
****************************************************************************
* DESCRIPTION:  this function is called upon receving data IAPP packet type 
*               while rx port status is "open"
* 
* INPUTS:       hRxData - the object
*               pBuffer - the received Buffer.
*               pRxAttr - Rx attributes
*       
* OUTPUT:       
* 
* RETURNS:      
***************************************************************************/
#ifdef XCC_MODULE_INCLUDED

static void rxData_rcvPacketIapp(TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr)
{
    rxData_t *pRxData = (rxData_t *)hRxData;

    TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_rcvPacketIapp() : Received IAPP frame tranferred to XCCMgr\n");

    TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_rcvPacketIapp() : Received IAPP frame tranferred to XCCMgr\n");

    /* tranfer packet to XCCMgr */
    XCCMngr_recvIAPPPacket (pRxData->hXCCMgr, pBuffer, pRxAttr);

    /* free Buffer */
    RxBufFree(pRxData->hOs, pBuffer); 
}

#endif


/****************************************************************************
*                       rxData_convertWlanToEthHeader                       *
*****************************************************************************
* DESCRIPTION:  this function convert the Packet header from 802.11 header 
*               format to ethernet format
* 
* INPUTS:       hRxData - the object
*               pBuffer - the received pBuffer in 802.11 format
*       
* OUTPUT:       pEthPacket  - pointer to the received pBuffer in ethernet format
*               uEthLength - ethernet packet length
* 
* RETURNS:      TI_OK/TI_NOK
***************************************************************************/
static TI_STATUS rxData_convertWlanToEthHeader (TI_HANDLE hRxData, void *pBuffer, TI_UINT16 * etherType)
{
    TEthernetHeader      EthHeader;
    Wlan_LlcHeader_T    *pWlanSnapHeader;   
    TI_UINT8            *dataBuf;
    dot11_header_t      *pDot11Header;
    TI_UINT32            lengthDelta;
    TI_UINT16            swapedTypeLength;
    TI_UINT32            headerLength;
    TI_UINT8             createEtherIIHeader;
    rxData_t *pRxData = (rxData_t *)hRxData;

    dataBuf = (TI_UINT8 *)RX_BUF_DATA(pBuffer);

    /* Setting the mac header len according to the received FrameControl field in the Mac Header */
    GET_MAX_HEADER_SIZE (dataBuf, &headerLength);
    pDot11Header = (dot11_header_t*) dataBuf;
    pWlanSnapHeader = (Wlan_LlcHeader_T*)((TI_UINT32)dataBuf + (TI_UINT32)headerLength);
    
    swapedTypeLength = WLANTOHS (pWlanSnapHeader->Type);
    *etherType = swapedTypeLength;
 
    /* Prepare the Ethernet header. */
    if( ENDIAN_HANDLE_WORD(pDot11Header->fc) & DOT11_FC_FROM_DS)
    {   /* Infrastructure  bss */
        MAC_COPY (EthHeader.dst, pDot11Header->address1);
        MAC_COPY (EthHeader.src, pDot11Header->address3);
    }
    else
    {   /* Independent bss */
        MAC_COPY (EthHeader.dst, pDot11Header->address1);
        MAC_COPY (EthHeader.src, pDot11Header->address2);
    }
    
    createEtherIIHeader = TI_FALSE;
	/* See if the LLC header in the frame shows the SAP SNAP... */
	if((SNAP_CHANNEL_ID == pWlanSnapHeader->DSAP) &&
	   (SNAP_CHANNEL_ID == pWlanSnapHeader->SSAP) &&
	   (LLC_CONTROL_UNNUMBERED_INFORMATION == pWlanSnapHeader->Control))
	{
		/* Check for the Bridge Tunnel OUI in the SNAP Header... */
		if((SNAP_OUI_802_1H_BYTE0 == pWlanSnapHeader->OUI[ 0 ]) &&
		   (SNAP_OUI_802_1H_BYTE1 == pWlanSnapHeader->OUI[ 1 ]) &&
		   (SNAP_OUI_802_1H_BYTE2 == pWlanSnapHeader->OUI[ 2 ]))
		{
			/* Strip the SNAP header by skipping over it.                  */
			/* Start moving data from the Ethertype field in the SNAP      */
			/* header.  Move to the TypeLength field in the 802.3 header.  */
			createEtherIIHeader = TI_TRUE;
		}
		/* Check for the RFC 1042 OUI in the SNAP Header   */
		else
		{
			/* Check for the RFC 1042 OUI in the SNAP Header   */
			if(	(SNAP_OUI_RFC1042_BYTE0 == pWlanSnapHeader->OUI[ 0 ]) &&
				(SNAP_OUI_RFC1042_BYTE1 == pWlanSnapHeader->OUI[ 1 ]) &&
				(SNAP_OUI_RFC1042_BYTE2 == pWlanSnapHeader->OUI[ 2 ]))
			{
			/* See if the Ethertype is in our selective translation table  */
			/* (Appletalk AARP and DIX II IPX are the two protocols in     */
			/* our 'table')                                                */
				if((ETHERTYPE_APPLE_AARP != swapedTypeLength) &&
					(ETHERTYPE_DIX_II_IPX != swapedTypeLength))
			{
				/* Strip the SNAP header by skipping over it. */
				createEtherIIHeader = TI_TRUE;
			}
		}
	}
    }

    if( createEtherIIHeader == TI_TRUE )
    {
    /* The LEN/TYPE bytes are set to TYPE, the entire WLAN+SNAP is removed.*/
    lengthDelta = headerLength + WLAN_SNAP_HDR_LEN - ETHERNET_HDR_LEN;
    EthHeader.type = pWlanSnapHeader->Type;
    }
    else
    {
	/* The LEN/TYPE bytes are set to frame LEN, only the WLAN header is removed, */
	/* the entire 802.3 or 802.2 header is not removed.*/
	lengthDelta = headerLength - ETHERNET_HDR_LEN;
	EthHeader.type = WLANTOHS((TI_UINT16)(RX_BUF_LEN(pBuffer) - headerLength));
    }
    
    /* Replace the 802.11 header and the LLC with Ethernet packet. */
    dataBuf += lengthDelta;
    os_memoryCopy (pRxData->hOs, dataBuf, (void*)&EthHeader, ETHERNET_HDR_LEN);
    RX_ETH_PKT_DATA(pBuffer) = dataBuf;
    RX_ETH_PKT_LEN(pBuffer)  = RX_BUF_LEN(pBuffer) - lengthDelta;

    return TI_OK;
}


/**
 * \brief convert A-MSDU to several ethernet packets
 * 
 * \param hRxData - the object
 * \param pBuffer - the received Buffer in A-MSDU 802.11n format
 * \param pRxAttr - Rx attributes
 * \return TI_OK on success or TI_NOK on failure 
 * 
 * \par Description
 * Static function
 * This function convert the A-MSDU Packet from A-MSDU 802.11n packet
 * format to several ethernet packets format and pass them to the OS layer
 *
 * \sa
 */ 
static TI_STATUS rxData_ConvertAmsduToEthPackets (TI_HANDLE hRxData, void *pBuffer, TRxAttr* pRxAttr)
{

    TEthernetHeader     *pMsduEthHeader;
    TEthernetHeader     *pEthHeader;
    Wlan_LlcHeader_T    *pWlanSnapHeader;   
    TI_UINT8            *pAmsduDataBuf;
    TI_UINT16            uAmsduDataLen;
    void                *pDataBuf;
    TI_UINT16            uDataLen;
    TI_UINT32            lengthDelta;
    TI_UINT16            swapedTypeLength;
    TI_UINT32            headerLength;
    rxDataPacketType_e   DataPacketType;
    rxData_t            *pRxData = (rxData_t *)hRxData;

    /* total AMPDU header */
    pAmsduDataBuf = (TI_UINT8 *)RX_BUF_DATA(pBuffer);
    /* Setting the mac header len according to the received FrameControl field in the Mac Header */
    GET_MAX_HEADER_SIZE (pAmsduDataBuf, &headerLength);
    
    /* 
     * init loop setting 
     */
    /* total AMPDU size */
    uAmsduDataLen = (TI_UINT16)(RX_BUF_LEN(pBuffer) - headerLength);
    /* ETH header */
    pMsduEthHeader = (TEthernetHeader *)(pAmsduDataBuf + headerLength);
    /* ETH length, in A-MSDU the MSDU header type contain the MSDU length and not the type */
    uDataLen = WLANTOHS(pMsduEthHeader->type);

    TRACE1(pRxData->hReport, REPORT_SEVERITY_INFORMATION, "rxData_ConvertAmsduToEthPackets(): A-MSDU received in length %d \n",uAmsduDataLen);

    /* if we have another packet at the AMSDU */
    while((uDataLen < uAmsduDataLen) && (uAmsduDataLen > ETHERNET_HDR_LEN + FCS_SIZE))  
    {
        /* allocate a new buffer */
        /* RxBufAlloc() add an extra word for alignment the MAC payload */
        rxData_RequestForBuffer (hRxData, &pDataBuf, sizeof(RxIfDescriptor_t) + WLAN_SNAP_HDR_LEN + ETHERNET_HDR_LEN + uDataLen, 0, TAG_CLASS_AMSDU);
        if (NULL == pDataBuf)
        {
            TRACE1(pRxData->hReport, REPORT_SEVERITY_ERROR, "rxData_ConvertAmsduToEthPackets(): cannot alloc MSDU packet. length %d \n",uDataLen);
            rxData_discardPacket (hRxData, pBuffer, pRxAttr);
            return TI_NOK;
        }

        /* read packet type from LLC */
        pWlanSnapHeader = (Wlan_LlcHeader_T*)((TI_UINT8*)pMsduEthHeader + ETHERNET_HDR_LEN);
        swapedTypeLength = WLANTOHS (pWlanSnapHeader->Type);

        /* copy the RxIfDescriptor */
        os_memoryCopy (pRxData->hOs, pDataBuf, pBuffer, sizeof(RxIfDescriptor_t));

        /* update length, in the RxIfDescriptor the Len in words (4B) */
        ((RxIfDescriptor_t *)pDataBuf)->length = (sizeof(RxIfDescriptor_t) + WLAN_SNAP_HDR_LEN + ETHERNET_HDR_LEN + uDataLen) >> 2;
        ((RxIfDescriptor_t *)pDataBuf)->extraBytes = 4 - ((sizeof(RxIfDescriptor_t) + WLAN_SNAP_HDR_LEN + ETHERNET_HDR_LEN + uDataLen) & 0x3);

        /* Prepare the Ethernet header pointer. */ 
        /* add padding in the start of the buffer in order to align ETH payload */
        pEthHeader = (TEthernetHeader *)((TI_UINT8 *)(RX_BUF_DATA(pDataBuf)) + 
                                         WLAN_SNAP_HDR_LEN + 
                                         PADDING_ETH_PACKET_SIZE);

        /* copy the Ethernet header */
        os_memoryCopy (pRxData->hOs, pEthHeader, pMsduEthHeader, ETHERNET_HDR_LEN);

        /* The LEN/TYPE bytes are set to TYPE */
        pEthHeader->type = pWlanSnapHeader->Type;

        /* Delta length for the next packet */
        lengthDelta = ETHERNET_HDR_LEN + uDataLen;

        /* copy the packet payload */
        if (uDataLen > WLAN_SNAP_HDR_LEN)
            os_memoryCopy (pRxData->hOs,
                       (((TI_UINT8*)pEthHeader) + ETHERNET_HDR_LEN), 
                       ((TI_UINT8*)pMsduEthHeader) + ETHERNET_HDR_LEN + WLAN_SNAP_HDR_LEN, 
                       uDataLen - WLAN_SNAP_HDR_LEN);

        /* set the packet type */
        if (swapedTypeLength == ETHERTYPE_802_1D)
        {
            TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_ConvertAmsduToEthPackets() : Received VLAN Buffer  \n");

            DataPacketType = DATA_VLAN_PACKET;
        }
        else if (HTOWLANS(pEthHeader->type) == EAPOL_PACKET)
        {
            TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_ConvertAmsduToEthPackets() : Received Eapol pBuffer  \n");

            DataPacketType = DATA_EAPOL_PACKET;
        }
        else
        {
            TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, " rxData_ConvertAmsduToEthPackets() : Received Data pBuffer  \n");

            DataPacketType = DATA_DATA_PACKET;
        }

        /* update buffer setting */
        /* save the ETH packet address */
        RX_ETH_PKT_DATA(pDataBuf) = pEthHeader;
        /* save the ETH packet size */
        RX_ETH_PKT_LEN(pDataBuf) = uDataLen + ETHERNET_HDR_LEN - WLAN_SNAP_HDR_LEN;

        /* star of MSDU packet always align acceding to 11n spec */
        lengthDelta = (lengthDelta + ALIGN_4BYTE_MASK) & ~ALIGN_4BYTE_MASK;
        pMsduEthHeader = (TEthernetHeader *)(((TI_UINT8*)pMsduEthHeader) + lengthDelta);

        if(uAmsduDataLen > lengthDelta)
        {
            /* swich to the next MSDU */
            uAmsduDataLen = uAmsduDataLen - lengthDelta;

            /* Clear the EndOfBurst flag for all packets except the last one */
            ((RxIfDescriptor_t *)pDataBuf)->driverFlags &= ~DRV_RX_FLAG_END_OF_BURST;
        }
        else
        {
            /* no more MSDU */
            uAmsduDataLen = 0;
        }


        /* in A-MSDU the MSDU header type contain the MSDU length and not the type */
        uDataLen = WLANTOHS(pMsduEthHeader->type);


        /* dispatch Buffer according to packet type and current rx data port status */
        pRxData->rxData_dispatchBuffer[pRxData->rxDataPortStatus][DataPacketType] (hRxData, pDataBuf, pRxAttr);

    } /* while end */


    TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION, "rxData_ConvertAmsduToEthPackets(): A-MSDU Packe conversion done.\n");

    /* free the A-MSDU packet */
    RxBufFree(pRxData->hOs, pBuffer);

    return TI_OK;
}

/****************************************************************************************
 *                        rxData_ReceivePacket                                              *
 ****************************************************************************************
DESCRIPTION:    receive packet CB from RxXfer.
                parse the status and other parameters and forward the frame to  
                rxData_receivePacketFromWlan()
                
INPUT:          Rx frame with its parameters    

OUTPUT:

RETURN:         

************************************************************************/
static void rxData_ReceivePacket (TI_HANDLE   hRxData,
                                  void  *pBuffer)
{
    rxData_t            *pRxData    = (rxData_t *)hRxData;

    TRACE1(pRxData->hReport, REPORT_SEVERITY_INFORMATION, "rxData_ReceivePacket: Received BUF %x\n", pBuffer);

    if (pBuffer)
    {
        RxIfDescriptor_t    *pRxParams  = (RxIfDescriptor_t*)pBuffer;
        TRxAttr             RxAttr; 
        ERate               appRate;
        dot11_header_t      *pHdr;

        /*
         * First thing we do is getting the dot11_header, and than we check the status, since the header is
         * needed for RX_MIC_FAILURE_ERROR 
         */

        pHdr = (dot11_header_t *)RX_BUF_DATA(pBuffer);

        /* Check status */
        switch (pRxParams->status & RX_DESC_STATUS_MASK)
        {
            case RX_DESC_STATUS_SUCCESS:
                break;
            
            case RX_DESC_STATUS_DECRYPT_FAIL:
            {
                /* This error is not important before the Connection, so we ignore it when portStatus is not OPEN */
                if (pRxData->rxDataPortStatus == OPEN) 
                {
                    TRACE0(pRxData->hReport, REPORT_SEVERITY_WARNING, "rxData_ReceivePacket: Received Packet with RX_DESC_DECRYPT_FAIL\n");
                }
            
                RxBufFree(pRxData->hOs, pBuffer); 
                return;
            }
            case RX_DESC_STATUS_MIC_FAIL:
            {
                TI_UINT8 uKeyType; 
                paramInfo_t Param;
                TMacAddr* pMac = &pHdr->address1; /* hold the first mac address */
                /* Get BSS type */
                Param.paramType = SITE_MGR_CURRENT_BSS_TYPE_PARAM;
                siteMgr_getParam (pRxData->hSiteMgr, &Param);
     
                /* For multicast/broadcast frames or in IBSS the key used is GROUP, else - it's Pairwise */
                if (MAC_MULTICAST(*pMac) || Param.content.siteMgrCurrentBSSType == BSS_INDEPENDENT)
                {
                    uKeyType = (TI_UINT8)KEY_TKIP_MIC_GROUP;
	                TRACE0(pRxData->hReport, REPORT_SEVERITY_ERROR, "rxData_ReceivePacket: Received Packet MIC failure. Type = Group\n");
                }
                /* Unicast on infrastructure */
                else 
                {
                    uKeyType = (TI_UINT8)KEY_TKIP_MIC_PAIRWISE;
	                TRACE0(pRxData->hReport, REPORT_SEVERITY_ERROR, "rxData_ReceivePacket: Received Packet MIC failure. Type = Pairwise\n");
                }
    
    
                rsn_reportMicFailure (pRxData->hRsn, &uKeyType, sizeof(uKeyType));
                RxBufFree(pRxData->hOs, pBuffer); 
                return;
            }
    
            case RX_DESC_STATUS_DRIVER_RX_Q_FAIL:
            {
                /* Rx queue error - free packet and return */
                TRACE0(pRxData->hReport, REPORT_SEVERITY_ERROR, "rxData_ReceivePacket: Received Packet with Rx queue error \n");
  
                RxBufFree(pRxData->hOs, pBuffer); 
                return;
            }

            default:    
                    /* Unknown error - free packet and return */
                    TRACE1(pRxData->hReport, REPORT_SEVERITY_ERROR, "rxData_ReceivePacket: Received Packet with unknown status = %d\n", (pRxParams->status & RX_DESC_STATUS_MASK));
    
                    RxBufFree(pRxData->hOs, pBuffer); 
                    return;
            }

        TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION , "Receive good Packet\n");
        
        if (rate_PolicyToDrv ((ETxRateClassId)(pRxParams->rate), &appRate) != TI_OK)
        {
            TRACE1(pRxData->hReport, REPORT_SEVERITY_ERROR , "rxData_ReceivePacket: can't convert hwRate=0x%x\n", pRxParams->rate);
        }
        
        /*
         * Set rx attributes 
         */ 
        RxAttr.channel    = pRxParams->channel;
        RxAttr.packetInfo = pRxParams->flags;
        RxAttr.ePacketType= pRxParams->packet_class_tag;
        RxAttr.Rate       = appRate;
        RxAttr.Rssi       = pRxParams->rx_level;
        RxAttr.SNR        = pRxParams->rx_snr;
        RxAttr.status     = pRxParams->status & RX_DESC_STATUS_MASK;
        /* for now J band not implemented */
        RxAttr.band       = ((pRxParams->flags & RX_DESC_BAND_MASK) == RX_DESC_BAND_A) ? 
                            RADIO_BAND_5_0_GHZ : RADIO_BAND_2_4_GHZ ;
        RxAttr.eScanTag   = (EScanResultTag)(pRxParams->proccess_id_tag);
        /* timestamp is 32 bit so do bytes copy to avoid exception in case the RxInfo is in 2 bytes offset */
        os_memoryCopy (pRxData->hOs,
                       (void *)&(RxAttr.TimeStamp), 
                       (void *)&(pRxParams->timestamp), 
                       sizeof(pRxParams->timestamp) );
        RxAttr.TimeStamp = ENDIAN_HANDLE_LONG(RxAttr.TimeStamp);

        TRACE8(pRxData->hReport, REPORT_SEVERITY_INFORMATION, "rxData_ReceivePacket: channel=%d, info=0x%x, type=%d, rate=0x%x, RSSI=%d, SNR=%d, status=%d, scan tag=%d\n", RxAttr.channel, RxAttr.packetInfo, RxAttr.ePacketType, RxAttr.Rate, RxAttr.Rssi, RxAttr.SNR, RxAttr.status, RxAttr.eScanTag);

        rxData_receivePacketFromWlan (hRxData, pBuffer, &RxAttr);

        /* 
         *  Buffer MUST be freed until now 
         */
    }
    else
    {
        TRACE0(pRxData->hReport, REPORT_SEVERITY_ERROR , "rxData_ReceivePacket: null Buffer received");
    }
}


/****************************************************************************************
 *                        rxData_RequestForBuffer                                              *
 ****************************************************************************************
DESCRIPTION:     RX request for buffer
                uEncryptionflag API are for GWSI use.
INPUT:          

OUTPUT:

RETURN:         

************************************************************************/
static ERxBufferStatus rxData_RequestForBuffer (TI_HANDLE   hRxData,
                                      void **pBuf,
                                      TI_UINT16 aLength, 
                                      TI_UINT32 uEncryptionflag,
                                      PacketClassTag_e ePacketClassTag)
{
    rxData_t *pRxData = (rxData_t *)hRxData;

    TRACE1(pRxData->hReport, REPORT_SEVERITY_INFORMATION , " RequestForBuffer, length = %d \n",aLength);

    *pBuf = RxBufAlloc (pRxData->hOs, aLength, ePacketClassTag);

    if (*pBuf)
    {
        return RX_BUF_ALLOC_COMPLETE;
    }
    else 
    {
        return RX_BUF_ALLOC_OUT_OF_MEM;
    }
}


/*******************************************************************
*                        DEBUG FUNCTIONS                           *
*******************************************************************/

#ifdef TI_DBG

/***************************************************************************
*                        rxData_resetCounters                              *
****************************************************************************
* DESCRIPTION:  This function reset the Rx Data module counters
*
* INPUTS:       hRxData - the object
*
* OUTPUT:       
* 
* RETURNS:      void
***************************************************************************/
void rxData_resetCounters(TI_HANDLE hRxData)
{
    rxData_t *pRxData = (rxData_t *)hRxData;

    os_memoryZero(pRxData->hOs, &pRxData->rxDataCounters, sizeof(rxDataCounters_t));
}

/***************************************************************************
*                        rxData_resetDbgCounters                           *
****************************************************************************
* DESCRIPTION:  This function reset the Rx Data module debug counters
*
* INPUTS:       hRxData - the object
*
* OUTPUT:       
* 
* RETURNS:      void
***************************************************************************/

void rxData_resetDbgCounters(TI_HANDLE hRxData)
{
    rxData_t *pRxData = (rxData_t *)hRxData;

    os_memoryZero(pRxData->hOs, &pRxData->rxDataDbgCounters, sizeof(rxDataDbgCounters_t));
}


/***************************************************************************
*                            test functions                                *
***************************************************************************/
void rxData_printRxCounters (TI_HANDLE hRxData)
{
#ifdef REPORT_LOG
    rxData_t *pRxData = (rxData_t *)hRxData;

    if (pRxData) 
    {
        WLAN_OS_REPORT(("RecvOk = %d\n", pRxData->rxDataCounters.RecvOk));
        WLAN_OS_REPORT(("DirectedBytesRecv = %d\n", pRxData->rxDataCounters.DirectedBytesRecv));
        WLAN_OS_REPORT(("DirectedFramesRecv = %d\n", pRxData->rxDataCounters.DirectedFramesRecv));
        WLAN_OS_REPORT(("MulticastBytesRecv = %d\n", pRxData->rxDataCounters.MulticastBytesRecv));
        WLAN_OS_REPORT(("MulticastFramesRecv = %d\n", pRxData->rxDataCounters.MulticastFramesRecv));
        WLAN_OS_REPORT(("BroadcastBytesRecv = %d\n", pRxData->rxDataCounters.BroadcastBytesRecv));
        WLAN_OS_REPORT(("BroadcastFramesRecv = %d\n", pRxData->rxDataCounters.BroadcastFramesRecv));
    
        /* debug counters */
        WLAN_OS_REPORT(("excludedFrameCounter = %d\n", pRxData->rxDataDbgCounters.excludedFrameCounter));
        WLAN_OS_REPORT(("rxDroppedDueToVLANIncludedCnt = %d\n", pRxData->rxDataDbgCounters.rxDroppedDueToVLANIncludedCnt));    
        WLAN_OS_REPORT(("rxWrongBssTypeCounter = %d\n", pRxData->rxDataDbgCounters.rxWrongBssTypeCounter));
        WLAN_OS_REPORT(("rxWrongBssIdCounter = %d\n", pRxData->rxDataDbgCounters.rxWrongBssIdCounter));
        WLAN_OS_REPORT(("rcvUnicastFrameInOpenNotify = %d\n", pRxData->rxDataDbgCounters.rcvUnicastFrameInOpenNotify));        
    }
#endif
}


void rxData_printRxBlock(TI_HANDLE hRxData)
{
#ifdef REPORT_LOG
    rxData_t *pRxData = (rxData_t *)hRxData;

    WLAN_OS_REPORT(("hCtrlData = 0x%X\n", pRxData->hCtrlData));
    WLAN_OS_REPORT(("hMlme = 0x%X\n", pRxData->hMlme));
    WLAN_OS_REPORT(("hOs = 0x%X\n", pRxData->hOs));
    WLAN_OS_REPORT(("hReport = 0x%X\n", pRxData->hReport));
    WLAN_OS_REPORT(("hRsn = 0x%X\n", pRxData->hRsn));
    WLAN_OS_REPORT(("hSiteMgr = 0x%X\n", pRxData->hSiteMgr));

    WLAN_OS_REPORT(("hCtrlData = 0x%X\n", pRxData->hCtrlData));
    WLAN_OS_REPORT(("hMlme = 0x%X\n", pRxData->hMlme));
    WLAN_OS_REPORT(("hOs = 0x%X\n", pRxData->hOs));
    WLAN_OS_REPORT(("hReport = 0x%X\n", pRxData->hReport));
    WLAN_OS_REPORT(("hRsn = 0x%X\n", pRxData->hRsn));
    WLAN_OS_REPORT(("hSiteMgr = 0x%X\n", pRxData->hSiteMgr));

    WLAN_OS_REPORT(("rxDataPortStatus = %d\n", pRxData->rxDataPortStatus));
    WLAN_OS_REPORT(("rxDataExcludeUnencrypted = %d\n", pRxData->rxDataExcludeUnencrypted));
    WLAN_OS_REPORT(("rxDataEapolDestination = %d\n", pRxData->rxDataEapolDestination));
#endif
}


void rxData_startRxThroughputTimer (TI_HANDLE hRxData)
{
    rxData_t *pRxData = (rxData_t *)hRxData;

    if (!pRxData->rxThroughputTimerEnable)
    {
        /* reset throughput counter */
        pRxData->rxDataCounters.LastSecBytesRecv = 0;
        pRxData->rxThroughputTimerEnable = TI_TRUE;

        /* start 1 sec throughput timer */
        tmr_StartTimer (pRxData->hThroughputTimer,
                        rxData_printRxThroughput,
                        (TI_HANDLE)pRxData,
                        1000,
                        TI_TRUE);
    }
}


void rxData_stopRxThroughputTimer (TI_HANDLE hRxData)
{

    rxData_t *pRxData = (rxData_t *)hRxData;

    if (pRxData->rxThroughputTimerEnable)
    {
        tmr_StopTimer (pRxData->hThroughputTimer);
        pRxData->rxThroughputTimerEnable = TI_FALSE;
    } 
}


static void rxData_printRxThroughput (TI_HANDLE hRxData, TI_BOOL bTwdInitOccured)
{
    rxData_t *pRxData = (rxData_t *)hRxData;

    WLAN_OS_REPORT (("\n"));
    WLAN_OS_REPORT (("-------------- Rx Throughput Statistics ---------------\n"));
    WLAN_OS_REPORT (("Throughput = %d KBits/sec\n", pRxData->rxDataCounters.LastSecBytesRecv * 8 / 1024));

    /* reset throughput counter */
    pRxData->rxDataCounters.LastSecBytesRecv = 0;
}

void rxData_printRxDataFilter (TI_HANDLE hRxData)
{
    TI_UINT32 index;
    rxData_t *pRxData = (rxData_t *)hRxData;

    for (index=0; index<MAX_DATA_FILTERS; index++)
     {
        if (pRxData->isFilterSet[index])
        {
            WLAN_OS_REPORT (("index=%d, pattern & mask\n", index));
            report_PrintDump(pRxData->filterRequests[index].pattern, pRxData->filterRequests[index].patternLength);
            report_PrintDump(pRxData->filterRequests[index].mask, pRxData->filterRequests[index].maskLength);
        }
        else
        {
            WLAN_OS_REPORT (("No Filter defined for index-%d\n", index));
        }
     }
}

#endif /*TI_DBG*/

/****************************************************************************
 *                      rxData_SetReAuthInProgress()
 ****************************************************************************
 * DESCRIPTION:	Sets the ReAuth flag value
 *
 * INPUTS: hRxData - the object
 *		   value - value to set the flag to
 *
 * OUTPUT:	None
 *
 * RETURNS:	OK or NOK
 ****************************************************************************/
void rxData_SetReAuthInProgress(TI_HANDLE hRxData, TI_BOOL	value)
{
	rxData_t *pRxData = (rxData_t *)hRxData;

	TRACE1(pRxData->hReport, REPORT_SEVERITY_INFORMATION , "Set ReAuth flag to %d\n", value);

	pRxData->reAuthInProgress = value;
}

/****************************************************************************
 *                      rxData_IsReAuthInProgress()
 ****************************************************************************
 * DESCRIPTION:	Returns the ReAuth flag value
 *
 * INPUTS: hRxData - the object
 *
 * OUTPUT:	None
 *
 * RETURNS:	ReAuth flag value
 ****************************************************************************/
TI_BOOL rxData_IsReAuthInProgress(TI_HANDLE hRxData)
{
	rxData_t *pRxData = (rxData_t *)hRxData;
	return pRxData->reAuthInProgress;
}

/****************************************************************************
*						rxData_StartReAuthActiveTimer   	                *
*****************************************************************************
* DESCRIPTION:	this function starts the ReAuthActive timer
*
* INPUTS:		hRxData - the object
*
* OUTPUT:		None
*
* RETURNS:		None
***************************************************************************/
static void rxData_StartReAuthActiveTimer(TI_HANDLE hRxData)
{
	rxData_t *pRxData = (rxData_t *)hRxData;
    TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION , "Start ReAuth Active Timer\n");
    tmr_StartTimer (pRxData->reAuthActiveTimer,
                    reAuthTimeout,
                    (TI_HANDLE)pRxData,
                    pRxData->reAuthActiveTimeout,
                    TI_FALSE);
}

/****************************************************************************
*						rxData_StopReAuthActiveTimer   						*
*****************************************************************************
* DESCRIPTION:	this function stops the ReAuthActive timer
*
* INPUTS:		hRxData - the object
*
* OUTPUT:		None
*
* RETURNS:		None
***************************************************************************/
void rxData_StopReAuthActiveTimer(TI_HANDLE hRxData)
{
	rxData_t *pRxData = (rxData_t *)hRxData;
    TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION , "Stop ReAuth Active Timer\n");
    tmr_StopTimer (pRxData->reAuthActiveTimer);
}

/****************************************************************************
*						reAuthTimeout   									*
*****************************************************************************
* DESCRIPTION:	this function ia called when the ReAuthActive timer elapses
*				It resets the Reauth flag and restore the PS state.
*				It also sends RE_AUTH_TERMINATED event to upper layer.
*
* INPUTS:		hRxData - the object
*
* OUTPUT:		None
*
* RETURNS:		None
***************************************************************************/
static void reAuthTimeout(TI_HANDLE hRxData, TI_BOOL bTwdInitOccured)
{
	rxData_t *pRxData = (rxData_t *)hRxData;

    TRACE0(pRxData->hReport, REPORT_SEVERITY_INFORMATION , "ReAuth Active Timeout\n");
	rxData_SetReAuthInProgress(pRxData, TI_FALSE);
	rxData_ReauthDisablePriority(pRxData);
    EvHandlerSendEvent(pRxData->hEvHandler, IPC_EVENT_RE_AUTH_TERMINATED, NULL, 0);
}

void rxData_ReauthEnablePriority(TI_HANDLE hRxData)
{
	rxData_t *pRxData = (rxData_t *)hRxData;
	paramInfo_t param;

    param.paramType = POWER_MGR_ENABLE_PRIORITY;
    param.content.powerMngPriority = POWER_MANAGER_REAUTH_PRIORITY;
    powerMgr_setParam(pRxData->hPowerMgr,&param);
}

void rxData_ReauthDisablePriority(TI_HANDLE hRxData)
{
	rxData_t *pRxData = (rxData_t *)hRxData;
    paramInfo_t param;

    param.paramType = POWER_MGR_DISABLE_PRIORITY;
    param.content.powerMngPriority = POWER_MANAGER_REAUTH_PRIORITY;
    powerMgr_setParam(pRxData->hPowerMgr,&param);
}
