diff options
Diffstat (limited to 'wilink_6_1/TWD/Data_Service/RxQueue.c')
-rw-r--r-- | wilink_6_1/TWD/Data_Service/RxQueue.c | 823 |
1 files changed, 823 insertions, 0 deletions
diff --git a/wilink_6_1/TWD/Data_Service/RxQueue.c b/wilink_6_1/TWD/Data_Service/RxQueue.c new file mode 100644 index 0000000..7f627be --- /dev/null +++ b/wilink_6_1/TWD/Data_Service/RxQueue.c @@ -0,0 +1,823 @@ +/* + * RxQueue.c + * + * Copyright(c) 1998 - 2009 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. + */ + + +/** \file RxQueue.c + * \brief RX Queue module that responsible to support re-ordering of received packets to upper layers. + * + * \see RxQueue.h + */ +#define __FILE_ID__ FILE_ID_98 +#include "tidef.h" +#include "osApi.h" +#include "report.h" +#include "RxBuf.h" +#include "TWDriver.h" +#include "public_descriptors.h" + +/************************ static definition declaration *****************************/ +#define RX_QUEUE_ARRAY_SIZE 8 +#define RX_QUEUE_ARRAY_SIZE_BIT_MASK 0x7 /* RX_QUEUE_ARRAY_SIZE -1 */ +#define RX_QUEUE_WIN_SIZE RX_QUEUE_ARRAY_SIZE + +#define BA_SESSION_IS_A_BIGGER_THAN_B(A,B) (((((A)-(B)) & 0xFFF) < 0x7FF) && ((A)!=(B))) +#define BA_SESSION_IS_A_BIGGER_EQUAL_THAN_B(A,B) (((((A)-(B)) & 0xFFF) < 0x7FF)) +#define SEQ_NUM_WRAP 0x1000 +#define SEQ_NUM_MASK 0xFFF + + +/************************ static structures declaration *****************************/ +/* structure describe one entry of save packet information in the packet queue array */ +typedef struct +{ + void *pPacket; /* Packet address of the packet */ + TI_STATUS tStatus; /* RxXfer status. */ + TI_UINT16 uFrameSn; +} TRxQueuePacketEntry; + +/* structure describe set of data that one Tid, also including the arras himself */ +typedef struct +{ + /* array packets Entries */ + TRxQueuePacketEntry aPaketsQueue [RX_QUEUE_ARRAY_SIZE]; + /* TID BA state */ + TI_BOOL aTidBaEstablished; + /* index that winStar point on */ + TI_UINT32 aWinStartArrayInex; + /* windows size */ + TI_UINT32 aTidWinSize; + /* expected sequence number (ESN) */ + TI_UINT16 aTidExpectedSn; +} TRxQueueTidDataBase; + +/* structure describe set of data that assist of manage one SA RxQueue arrays */ +typedef struct +{ + TRxQueueTidDataBase tSa1ArrayMng [MAX_NUM_OF_802_1d_TAGS]; +} TRxQueueArraysMng; + +/* main RxQueue structure in order to management the packets disordered array. */ +typedef struct +{ + TI_HANDLE hOs; /* OS handler */ + TI_HANDLE hReport; /* Report handler */ + TRxQueueArraysMng tRxQueueArraysMng; /* manage each Source Address RxQueue arrays */ + TPacketReceiveCb tReceivePacketCB; /* Receive packets CB address */ + TI_HANDLE hReceivePacketCB_handle; /* Receive packets CB handler */ + +} TRxQueue; + +/************************ static function declaration *****************************/ +static TI_STATUS RxQueue_PassPacket (TI_HANDLE hRxQueue, TI_STATUS tStatus, const void *pBuffer); + +/** + * \fn RxQueue_Create() + * \brief Create the RxQueue module. + * + * Allocate and clear the RxQueue module object. + * + * \param hOs - Handle to Os Abstraction Layer + * \return Handle of the allocated object + * \sa RxQueue_Destroy + */ +TI_HANDLE RxQueue_Create (TI_HANDLE hOs) +{ + TRxQueue *pRxQueue; + + /* allocate module object */ + pRxQueue = os_memoryAlloc (hOs, sizeof(TRxQueue)); + + if (!pRxQueue) + { + WLAN_OS_REPORT (("RxQueue_Create(): Allocation failed!!\n")); + return NULL; + } + + os_memoryZero (hOs, pRxQueue, (sizeof(TRxQueue))); + + pRxQueue->hOs = hOs; + + return (pRxQueue); +} + + +/** + * \fn RxQueue_Destroy() + * \brief Destroy the module. + * + * Free the module's queues and object. + * + * \param hRxQueue - The module object + * \return TI_OK on success or TI_NOK on failure + * \sa RxQueue_Create + */ +TI_STATUS RxQueue_Destroy (TI_HANDLE hRxQueue) +{ + TRxQueue *pRxQueue = (TRxQueue *)hRxQueue; + + /* free module object */ + os_memoryFree (pRxQueue->hOs, pRxQueue, sizeof(TRxQueue)); + + return TI_OK; +} + + +/** + * \fn RxQueue_Init() + * \brief Init required handles + * + * Init required handles and module variables. + * + * \note + * \param hRxQueue - The module object + * \param hReport - Report module Handles + * \return TI_OK on success or TI_NOK on failure + * \sa + */ +TI_STATUS RxQueue_Init (TI_HANDLE hRxQueue, TI_HANDLE hReport) +{ + TRxQueue *pRxQueue = (TRxQueue *)hRxQueue; + + pRxQueue->hReport = hReport; + + return TI_OK; +} + + +/** + * \fn RxQueue_Register_CB() + * \brief Register the function to be called for received Rx. + * + * \note + * \param hRxQueue - The module object + * \param CallBackID - event ID + * \param CBFunc - function address. + * \param CBObj - function parameter. + * \return TI_OK on success or TI_NOK on failure + * \sa + */ +void RxQueue_Register_CB (TI_HANDLE hRxQueue, TI_UINT32 uCallBackID, void *CBFunc, TI_HANDLE CBObj) +{ + TRxQueue* pRxQueue = (TRxQueue *)hRxQueue; + + TRACE1(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION , "RxQueue_Register_CB: CallBack ID = 0x%x\n", uCallBackID); + + switch(uCallBackID) + { + case TWD_INT_RECEIVE_PACKET: + pRxQueue->tReceivePacketCB = (TPacketReceiveCb)CBFunc; + pRxQueue->hReceivePacketCB_handle = CBObj; + break; + + default: + TRACE0(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_Register_CB: Illegal value\n"); + break; + } +} + +/** + * \fn RxQueue_CloseBaSession () + * \brief Close BA session receiver and pass all packets in the TID queue to upper layer. + * + * \note + * \param hRxQueue - RxQueue handle. + * \param uFrameTid - TID session. + * \return None + * \sa + */ +void RxQueue_CloseBaSession(TI_HANDLE hRxQueue, TI_UINT8 uFrameTid) +{ + TRxQueue *pRxQueue = (TRxQueue *)hRxQueue; + TI_UINT32 i; + /*set the SA Tid pointer */ + TRxQueueTidDataBase *pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]); + + /* TID illegal value ? */ + if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS) + { + TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_CloseBaSession: BA event - DELBA frame with TID value too big, TID = %d\n", uFrameTid); + + return; + } + + if(pTidDataBase->aTidBaEstablished == TI_TRUE) + { + /* clean BA session */ + pTidDataBase->aTidBaEstablished = TI_FALSE; + + /* pass all valid entries at the array */ + for (i = 0; (i < RX_QUEUE_ARRAY_SIZE) && (i < RX_QUEUE_WIN_SIZE); i++) + { + if (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL) + { + RxQueue_PassPacket (pRxQueue, + pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus, + pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket); + + pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL; + } + + pTidDataBase->aWinStartArrayInex ++; + + /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ + pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; + } + } +} + + +/** + * \fn RxQueue_PassPacket() + * \brief Responsible on decode packet parameters and pass it to upper layer. + * + * \note + * \param hRxQueue - RxQueue handle. + * \param aStatus - RxXfer status that indicate if the upper layer should free the packet or use it. + * \param pFrame - paket address of the packet + * \param pRxParams - address to structure of the Rx Descriptor received by FW. + * \return TI_OK on success or TI_NOK on failure + * \sa + */ +static TI_STATUS RxQueue_PassPacket (TI_HANDLE hRxQueue, TI_STATUS tStatus, const void *pBuffer) +{ + + TRxQueue *pRxQueue = (TRxQueue *)hRxQueue; + + if (tStatus == TI_OK) + { + /* Get the mac header location in the packet Buffer */ + dot11_header_t *pMacHdr = (dot11_header_t *)(TI_UINT8*)RX_BUF_DATA(pBuffer); + + /* Handle endian for the frame control fields */ + pMacHdr->fc = ENDIAN_HANDLE_WORD(pMacHdr->fc); + pMacHdr->duration = ENDIAN_HANDLE_WORD(pMacHdr->duration); + pMacHdr->seqCtrl = ENDIAN_HANDLE_WORD(pMacHdr->seqCtrl); + } + else + { + RxIfDescriptor_t *pRxParams = (RxIfDescriptor_t*)pBuffer; + + pRxParams->status &= ~RX_DESC_STATUS_MASK; + pRxParams->status |= RX_DESC_STATUS_DRIVER_RX_Q_FAIL; + } + + TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION , "RxQueue_PassPacket: call TWD_OWNER_RX_QUEUE CB. In std rxData_ReceivePacket()\n"); + + /* Set the packet to upper layer */ + /* if the packet status not success it will be discarded */ + pRxQueue->tReceivePacketCB (pRxQueue->hReceivePacketCB_handle, pBuffer); + + return TI_OK; +} + + +/** + * \fn RxQueue_ReceivePacket() + * \brief Main function of the RxQueue module. + * Responsible on reorder of the packets from the RxXfer to the RX module. + * Call from RxXfer in order to pass packet to uppers layers. + * In order to save disordered packets the module use array of structures per TID + * that each entry describe a packet. The array elements is sorted in the way that + * the winStart array index represent always the winStar packet and the lowest SN. + * Each increment index represent index at the BA window. Array index winEnd always + * represent winEnd packet. The indexes of winStart and winEnd handled in cyclic manner. + * The function functionality devided to parts: + * Part 1: + * in case the modulo receive packet with SN equal to winStart: + * " pass it to upper layers + * " increases winStart and array index winStart + * " validate that all sequential queue packet are pass to the upper layers. + * Part 2: + * in case the modulo receive packet that SN between winStart to winEnd: + * " Save it sorted at the array at index: Save index = ((SN - winStart) + index array winStart) % arraySize. + * Part 3: + * in case the modulo receive packet that SN higher then winEnd: + * " Update winStart and WinEnd. + * " Save it sorted at the array in index winEnd index. + * " Pass to the upper layers all packets at the array indexes from old winStart index to the updated winStart index. + * Part 4 + 5: + * in case the modulo receive BA event packet: + * " Update winStart and WinEnd + * " Pass to the upper layers all packets at the array indexes from old winStart index to the updated winStart index. + * " Free BA event packet via pass it to upper layers with error status. + * + * \note + * \param hRxQueue - RxQueue handle. + * \param aStatus - RxXfer status that indicate if the upper layer should free the packet or use it. + * \param pBuffer - paket address of the packet + * \return None + * \sa + */ +void RxQueue_ReceivePacket (TI_HANDLE hRxQueue, const void * pBuffer) +{ + TRxQueue *pRxQueue = (TRxQueue *)hRxQueue; + RxIfDescriptor_t *pRxParams = (RxIfDescriptor_t*)pBuffer; + TI_UINT8 *pFrame = RX_BUF_DATA((TI_UINT8 *)pBuffer); + TI_STATUS tStatus = TI_OK; + dot11_header_t *pHdr = (dot11_header_t *)pFrame; + TI_UINT16 uQosControl; + + COPY_WLAN_WORD(&uQosControl, &pHdr->qosControl); /* copy with endianess handling. */ + + /* + * Retrieving the TAG from the packet itself and not from the Rx Descriptor since by now it is not correct + * Note: in the DR TAG_CLASS_EAPOL packet handled as TAG_CLASS_QOS_DATA + */ + if (IS_QOS_FRAME(*(TI_UINT16*)pFrame) && (pRxParams->packet_class_tag != TAG_CLASS_QOS_DATA) && (pRxParams->packet_class_tag != TAG_CLASS_AMSDU)) + { + TRACE1(pRxQueue->hReport, REPORT_SEVERITY_WARNING, "RxQueue_ReceivePacket: BAD CLASS TAG =0x%x from FW.\n", pRxParams->packet_class_tag); + + /* Get AMSDU bit from frame */ + if( uQosControl & DOT11_QOS_CONTROL_FIELD_A_MSDU_BITS) + { + pRxParams->packet_class_tag = TAG_CLASS_AMSDU; + } + else + { + pRxParams->packet_class_tag = TAG_CLASS_QOS_DATA; + } + } + + /* + * packet doesn't need reorder ? + */ + if ((pRxParams->packet_class_tag != TAG_CLASS_QOS_DATA) && (pRxParams->packet_class_tag != TAG_CLASS_BA_EVENT) && (pRxParams->packet_class_tag != TAG_CLASS_AMSDU)) + { + TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: pass packet without reorder.\n"); + + RxQueue_PassPacket (pRxQueue, tStatus, pBuffer); + + return; + } + + + /* + * pRxParams->type == TAG_CLASS_QOS_DATA ? + */ + if ((pRxParams->packet_class_tag == TAG_CLASS_QOS_DATA) || (pRxParams->packet_class_tag == TAG_CLASS_AMSDU)) + { + TI_UINT8 uFrameTid; + TI_UINT16 uFrameSn; + TI_UINT16 uSequenceControl; + TRxQueueTidDataBase *pTidDataBase; + + /* Get TID from frame */ + uFrameTid = uQosControl & DOT11_QOS_CONTROL_FIELD_TID_BITS; + + /* TID illegal value ? */ + if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS) + { + TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR, "RxQueue_ReceivePacket: TID value too big, TID = %d. packet discarded!\n",uFrameTid); + + RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); + + return; + } + + /*set the SA Tid pointer */ + pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]); + + /* TID legal value */ + /* packet TID BA not established ? */ + if (pTidDataBase->aTidBaEstablished != TI_TRUE) + { + TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: pass packet without reorder.\n"); + + RxQueue_PassPacket (pRxQueue, tStatus, pBuffer); + + return; + } + + /* packet TID BA established */ + /* Get Sequence Number from frame */ + COPY_WLAN_WORD(&uSequenceControl, &pHdr->seqCtrl); /* copy with endianess handling. */ + uFrameSn = (uSequenceControl & DOT11_SC_SEQ_NUM_MASK) >> 4; + + /* + * note: + * the FW never send paket, in establish TID BA, that the SN less then ESN !!! + */ + + /* frame Sequence Number is the expected one ? */ + if (uFrameSn == pTidDataBase->aTidExpectedSn) + { + TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: frame Sequence Number == expected one Sequence Number.\n"); + + /* pass the packet */ + RxQueue_PassPacket (pRxQueue, tStatus, pBuffer); + + pTidDataBase->aTidExpectedSn++; + pTidDataBase->aTidExpectedSn &= 0xfff; + + /* increase the ArrayInex to the next */ + pTidDataBase->aWinStartArrayInex++; + + /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ + pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; + + /* pass all saved queue packets with SN higher then the expected one */ + while (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL) + { + RxQueue_PassPacket (pRxQueue, + pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus, + pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket); + + pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL; + + pTidDataBase->aWinStartArrayInex++; + + /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ + pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; + + pTidDataBase->aTidExpectedSn++; + pTidDataBase->aTidExpectedSn &= 0xfff; + } + + return; + } + + /* frame Sequence Number is lower then Expected sequence number (ISN) ? */ + if (! BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn, pTidDataBase->aTidExpectedSn)) + { + /* WLAN_OS_REPORT(("%s: ERROR - SN=%u is less than ESN=%u\n", __FUNCTION__, uFrameSn, pTidDataBase->aTidExpectedSn)); */ + + TRACE2(pRxQueue->hReport, REPORT_SEVERITY_ERROR, + "RxQueue_ReceivePacket: frame SN=%u is less than ESN=%u\n",uFrameSn,pTidDataBase->aTidExpectedSn); + + RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); + + return; + } + + /* frame Sequence Number between winStart and winEnd ? */ + if ((BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn, pTidDataBase->aTidExpectedSn)) && + /* mean: uFrameSn <= pTidDataBase->aTidExpectedSn + pTidDataBase->aTidWinSize) */ + ( ! BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn,(pTidDataBase->aTidExpectedSn + pTidDataBase->aTidWinSize - 1)))) + { + TI_UINT16 uSaveInex = pTidDataBase->aWinStartArrayInex + (TI_UINT16)((uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidExpectedSn) & SEQ_NUM_MASK); + /* uSaveInex % RX_QUEUE_ARRAY_SIZE */ + uSaveInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; + + + if (pTidDataBase->aPaketsQueue[uSaveInex].pPacket == NULL) + { + /* save the packet in the queue */ + pTidDataBase->aPaketsQueue[uSaveInex].tStatus = tStatus; + pTidDataBase->aPaketsQueue[uSaveInex].pPacket = (void *)pBuffer; + pTidDataBase->aPaketsQueue[uSaveInex].uFrameSn = uFrameSn; + } + else + { + TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR, "RxQueue_ReceivePacket: frame Sequence has allready saved. uFrameSn = %d\n",uFrameSn); + RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); + return; + } + return; + } + + + /* + frame Sequence Number higher then winEnd ? + */ + if ( BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn, (pTidDataBase->aTidExpectedSn + pTidDataBase->aTidWinSize - 1)) ) + { + TI_UINT32 i; + TI_UINT16 uNewWinStartSn = (uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidWinSize + 1) & SEQ_NUM_MASK; + TI_UINT16 uSaveInex; + + TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: frame Sequence Number higher then winEnd.\n"); + + /* increase the ArrayInex to the next */ + pTidDataBase->aWinStartArrayInex++; + + /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ + pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; + + /* update the Expected SN since the current one is lost */ + pTidDataBase->aTidExpectedSn++; + pTidDataBase->aTidExpectedSn &= 0xFFF; + + /* pass all saved queue packets with SN lower then the new win start */ + for (i = 0; + BA_SESSION_IS_A_BIGGER_THAN_B(uNewWinStartSn,pTidDataBase->aTidExpectedSn) && + (i < RX_QUEUE_ARRAY_SIZE) && + (i < pTidDataBase->aTidWinSize); + i++) + { + if (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL) + { + RxQueue_PassPacket (pRxQueue, + pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus, + pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket); + + pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL; + } + + pTidDataBase->aWinStartArrayInex++; + + /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ + pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; + + pTidDataBase->aTidExpectedSn++; + pTidDataBase->aTidExpectedSn &= 0xFFF; + + } + + /* Calculate the new Expected SN */ + if (i == pTidDataBase->aTidWinSize) + { + pTidDataBase->aTidExpectedSn = uNewWinStartSn; + } + else + { + /* Incase the uWinStartDelta lower than aTidWinSize check if ther are packets stored in Array */ + while (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL) { + RxQueue_PassPacket (pRxQueue, + pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus, + pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket); + + pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL; + + pTidDataBase->aWinStartArrayInex++; + + /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ + pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; + + pTidDataBase->aTidExpectedSn++; + pTidDataBase->aTidExpectedSn &= 0xFFF; + } + } + + if(pTidDataBase->aTidExpectedSn == uFrameSn) + { + /* pass the packet */ + RxQueue_PassPacket (pRxQueue, tStatus, pBuffer); + pTidDataBase->aTidExpectedSn++; + pTidDataBase->aTidExpectedSn &= 0xfff; + } + else + { + uSaveInex = pTidDataBase->aWinStartArrayInex + (TI_UINT16)((uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidExpectedSn) & SEQ_NUM_MASK); + + /* uSaveInex % RX_QUEUE_ARRAY_SIZE */ + uSaveInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; + + /* save the packet in the last entry of the queue */ + pTidDataBase->aPaketsQueue[uSaveInex].tStatus = tStatus; + pTidDataBase->aPaketsQueue[uSaveInex].pPacket = (void *)pBuffer; + pTidDataBase->aPaketsQueue[uSaveInex].pPacket = (void *)pBuffer; + } + + return; + } + } + + + /* + * BA event ? + */ + if (pRxParams->packet_class_tag == TAG_CLASS_BA_EVENT) + { + TRxQueueTidDataBase *pTidDataBase; + TI_UINT8 *pDataFrameBody; + TI_UINT16 ufc; + TI_UINT8 uFrameTid; + TI_UINT16 uStartingSequenceNumber; + TI_UINT16 uWinStartDelta; + TI_UINT16 uBarControlField; + TI_UINT16 uBaStartingSequenceControlField; + TI_UINT16 uBAParameterField; + TI_UINT32 i; + + /* Get sub type from frame */ + COPY_WLAN_WORD(&ufc, &pHdr->fc); /* copy with endianess handling. */ + + /* get the type to BA event */ + switch ((dot11_Fc_Sub_Type_e)(ufc & DOT11_FC_SUB_MASK)) + { + case DOT11_FC_SUB_BAR: + TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION , "RxQueue_ReceivePacket: BA event - BAR frame.\n"); + + /* get pointer to the frame body */ + pDataFrameBody = pFrame + sizeof(dot11_BarFrameHeader_t); + + /* Get TID from BAR frame */ + COPY_WLAN_WORD (&uBarControlField, (TI_UINT16 *)pDataFrameBody); /* copy with endianess handling. */ + uFrameTid = (uBarControlField & DOT11_BAR_CONTROL_FIELD_TID_BITS) >> 12; + + /* TID illegal value ? */ + if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS) + { + TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - BAR frame with TID value too big, TID = %d.\n",uFrameTid); + + RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); + + return; + } + + /* set the SA Tid pointer */ + pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]); + + /* TID legal value */ + /* packet TID BA not established ? */ + if (pTidDataBase->aTidBaEstablished != TI_TRUE) + { + TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - BAR frame for TID not established, TID = %d.\n",uFrameTid); + + RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); + + return; + } + + /* Get Starting Sequence number from BAR frame */ + pDataFrameBody = pDataFrameBody + 2; + COPY_WLAN_WORD (&uBaStartingSequenceControlField, (TI_UINT16 *)pDataFrameBody); /* copy with endianess handling. */ + uStartingSequenceNumber = (uBaStartingSequenceControlField & DOT11_SC_SEQ_NUM_MASK) >> 4; + + /* Starting Sequence Number is higher then winStart ? */ + if ( BA_SESSION_IS_A_BIGGER_THAN_B (uStartingSequenceNumber, pTidDataBase->aTidExpectedSn) ) + { + uWinStartDelta = (uStartingSequenceNumber + SEQ_NUM_WRAP - pTidDataBase->aTidExpectedSn) & SEQ_NUM_MASK; + + /* pass all saved queue packets with SN lower then the new win start */ + for (i = 0; + ((i < uWinStartDelta) || (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL)) && + (i < RX_QUEUE_ARRAY_SIZE) && + (i < RX_QUEUE_WIN_SIZE); + i++) + { + if (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL) + { + RxQueue_PassPacket (pRxQueue, + pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus, + pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket); + + pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL; + } + + pTidDataBase->aWinStartArrayInex++; + + /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */ + pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK; + } + + pTidDataBase->aTidExpectedSn = uStartingSequenceNumber; + } + break; + + + case DOT11_FC_SUB_ACTION: + /* get pointer to the frame body */ + pDataFrameBody = pFrame + sizeof(dot11_mgmtHeader_t); + + /* get Action field from BA action frame */ + pDataFrameBody++; + switch(*pDataFrameBody) + { + case DOT11_BA_ACTION_ADDBA: + + TRACE0( pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: BA event - ADDBA frame.\n"); + + /* get TID field and winSize from ADDBA action frame */ + pDataFrameBody = pDataFrameBody + 2; + COPY_WLAN_WORD(&uBAParameterField, (TI_UINT16 *)pDataFrameBody); /* copy with endianess handling. */ + uFrameTid = (uBAParameterField & DOT11_BA_PARAMETER_SET_FIELD_TID_BITS) >> 2; + + /* TID illegal value ? */ + if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS) + { + TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - ADDBA frame with TID value too big, TID = %d.\n",uFrameTid); + + RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); + + return; + } + + /*set the SA Tid pointer */ + pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]); + + /* TID legal value */ + /* packet TID BA established ? */ + if (pTidDataBase->aTidBaEstablished == TI_TRUE) + { + TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - ADDBA frame for TID already established, TID = %d.\n",uFrameTid); + + RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); + + return; + } + + /* get winSize from ADDBA action frame */ + pTidDataBase->aTidWinSize = (uBAParameterField & DOT11_BA_PARAMETER_SET_FIELD_WINSIZE_BITS) >> 6; + + /* winSize illegal value ? */ + if (pTidDataBase->aTidWinSize > RX_QUEUE_WIN_SIZE) + { + /* In case the win Size is higher then 8 the driver and the FW set it to 8 and inform the AP in ADDBA respond */ + pTidDataBase->aTidWinSize = RX_QUEUE_WIN_SIZE; + } + + /* packet TID BA not yet established and winSize legal */ + /* establishe BA TID */ + pTidDataBase->aTidBaEstablished = TI_TRUE; + + /* get initial sequence number (ISN) from ADDBA action frame */ + pDataFrameBody = pDataFrameBody + 4; + COPY_WLAN_WORD (&uStartingSequenceNumber, (TI_UINT16 *)pDataFrameBody); /* copy with endianess handling. */ + pTidDataBase->aTidExpectedSn = (uStartingSequenceNumber & DOT11_SC_SEQ_NUM_MASK) >> 4; + pTidDataBase->aWinStartArrayInex = 0; + os_memoryZero (pRxQueue->hOs, pTidDataBase->aPaketsQueue, sizeof (TRxQueuePacketEntry) * RX_QUEUE_ARRAY_SIZE); + break; + + case DOT11_BA_ACTION_DELBA: + + TRACE0( pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: BA event - DELBA frame.\n"); + + /* get TID field and winSize from ADDBA action frame */ + pDataFrameBody = pDataFrameBody + 2; + COPY_WLAN_WORD(&uBAParameterField, (TI_UINT16 *)pDataFrameBody); /* copy with endianess handling. */ + uFrameTid = (uBAParameterField & DOT11_DELBA_PARAMETER_FIELD_TID_BITS) >> 12; + + /* TID illegal value ? */ + if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS) + { + TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - DELBA frame with TID value too big, TID = %d.\n",uFrameTid); + + RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); + + return; + } + + /*set the SA Tid pointer */ + pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]); + + /* TID legal value */ + /* packet TID BA not established ? */ + if (pTidDataBase->aTidBaEstablished != TI_TRUE) + { + TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - DELBA frame for TID not established, TID = %d.\n",uFrameTid); + + RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); + + return; + } + + RxQueue_CloseBaSession(hRxQueue, uFrameTid); + break; + + default: + TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event Action field from BA action frame illegal. action = 0x%x\n",*pDataFrameBody); + + RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); + + return; + } + break; + + default: + TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event with Subtype illegal. Subtype = 0x%x\n",((ufc & DOT11_FC_SUB_MASK) >> 4)); + + RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer); + + return; + } + + } + + TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR, "RxQueue_ReceivePacket: unknow type tag. tag = %d\n", pRxParams->packet_class_tag); + + RxQueue_PassPacket (pRxQueue, tStatus, pBuffer); + + return; +} + |