summaryrefslogtreecommitdiff
path: root/wilink_6_1/TWD/Data_Service/RxQueue.c
diff options
context:
space:
mode:
Diffstat (limited to 'wilink_6_1/TWD/Data_Service/RxQueue.c')
-rw-r--r--wilink_6_1/TWD/Data_Service/RxQueue.c823
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;
+}
+