1/*
2 * RxQueue.c
3 *
4 * Copyright(c) 1998 - 2010 Texas Instruments. All rights reserved.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 *  * Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 *  * Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in
15 *    the documentation and/or other materials provided with the
16 *    distribution.
17 *  * Neither the name Texas Instruments nor the names of its
18 *    contributors may be used to endorse or promote products derived
19 *    from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34
35/** \file   RxQueue.c
36 *  \brief  RX Queue module that responsible to support re-ordering of received packets to upper layers.
37 *
38 *  \see    RxQueue.h
39 */
40#define __FILE_ID__  FILE_ID_98
41#include "tidef.h"
42#include "osApi.h"
43#include "report.h"
44#include "RxBuf.h"
45#include "TWDriver.h"
46#include "public_descriptors.h"
47#include "timer.h"
48
49/************************ static definition declaration *****************************/
50#define RX_QUEUE_ARRAY_SIZE		                            8
51#define RX_QUEUE_ARRAY_SIZE_BIT_MASK                        0x7 /* RX_QUEUE_ARRAY_SIZE -1 */
52#define RX_QUEUE_WIN_SIZE		                            RX_QUEUE_ARRAY_SIZE
53#define BA_SESSION_TIME_TO_SLEEP		                    (50)
54
55#define BA_SESSION_IS_A_BIGGER_THAN_B(A,B)       (((((A)-(B)) & 0xFFF) < 0x7FF) && ((A)!=(B)))
56#define BA_SESSION_IS_A_BIGGER_EQUAL_THAN_B(A,B) (((((A)-(B)) & 0xFFF) < 0x7FF))
57#define SEQ_NUM_WRAP 0x1000
58#define SEQ_NUM_MASK 0xFFF
59
60
61/************************ static structures declaration *****************************/
62/* structure describe one entry of save packet information in the packet queue array */
63typedef struct
64{
65    void                *pPacket;	/* Packet address of the packet */
66    TI_STATUS	        tStatus;	/* RxXfer status. */
67    TI_UINT16           uFrameSn;
68} TRxQueuePacketEntry;
69
70/* structure describe set of data that one Tid, also including the arras himself */
71typedef struct
72{
73    /* array packets Entries */
74    TRxQueuePacketEntry aPaketsQueue [RX_QUEUE_ARRAY_SIZE];
75    /* TID BA state */
76    TI_BOOL	            aTidBaEstablished;
77    /* index that winStar point on */
78    TI_UINT32 	        aWinStartArrayInex;
79    /* windows size */
80    TI_UINT32	        aTidWinSize;
81	/* expected sequence number (ESN) */
82    TI_UINT16	        aTidExpectedSn;
83} TRxQueueTidDataBase;
84
85/* structure describe set of data that assist of manage one SA RxQueue arrays */
86typedef struct
87{
88    TRxQueueTidDataBase tSa1ArrayMng [MAX_NUM_OF_802_1d_TAGS];
89} TRxQueueArraysMng;
90
91typedef struct
92{
93    TI_BOOL             bPacketMiss;                /* True - Wait for missing packets start timer
94                                                       False - all packets received in order */
95    TI_UINT16           aPacketsStored;             /* Represent the number of packets in Queue, 0 - Queue is empty */
96    TI_UINT8            aFrameTid;                  /* save the TID of the missing packet */
97} TPacketTimeout;
98
99
100/* main RxQueue structure in order to management the packets disordered array. */
101typedef struct
102{
103    TI_HANDLE           hOs;                        /* OS handler */
104    TI_HANDLE           hReport;                    /* Report handler */
105	TI_HANDLE           hTimer;                     /* Timer Handle */
106    TRxQueueArraysMng   tRxQueueArraysMng;          /* manage each Source Address RxQueue arrays */
107    TPacketReceiveCb    tReceivePacketCB;           /* Receive packets CB address */
108    TI_HANDLE           hReceivePacketCB_handle;    /* Receive packets CB handler */
109	TPacketTimeout      tPacketTimeout;             /* save information about the missing packet */
110} TRxQueue;
111
112/************************ static function declaration *****************************/
113static TI_STATUS RxQueue_PassPacket (TI_HANDLE hRxQueue, TI_STATUS tStatus, const void *pBuffer);
114static void RxQueue_PacketTimeOut (TI_HANDLE hRxQueue, TI_BOOL bTwdInitOccured);
115
116/**
117 * \fn     RxQueue_Create()
118 * \brief  Create the RxQueue module.
119 *
120 * Allocate and clear the RxQueue module object.
121 *
122 * \param  hOs - Handle to Os Abstraction Layer
123 * \return Handle of the allocated object
124 * \sa     RxQueue_Destroy
125 */
126TI_HANDLE RxQueue_Create (TI_HANDLE hOs)
127{
128	TRxQueue *pRxQueue;
129
130	/* allocate module object */
131	pRxQueue = os_memoryAlloc (hOs, sizeof(TRxQueue));
132
133	if (!pRxQueue)
134	{
135		WLAN_OS_REPORT (("RxQueue_Create():  Allocation failed!!\n"));
136		return NULL;
137	}
138
139    os_memoryZero (hOs, pRxQueue, (sizeof(TRxQueue)));
140
141    pRxQueue->hOs = hOs;
142
143	return (pRxQueue);
144}
145
146
147/**
148 * \fn     RxQueue_Destroy()
149 * \brief  Destroy the module.
150 *
151 * Free the module's queues and object.
152 *
153 * \param  hRxQueue - The module object
154 * \return TI_OK on success or TI_NOK on failure
155 * \sa     RxQueue_Create
156 */
157TI_STATUS RxQueue_Destroy (TI_HANDLE hRxQueue)
158{
159    TRxQueue *pRxQueue;
160
161    if (hRxQueue) {
162        pRxQueue = (TRxQueue *)hRxQueue;
163
164        if (pRxQueue->hTimer) {
165            tmr_DestroyTimer (pRxQueue->hTimer);
166            pRxQueue->hTimer = NULL;
167        }
168
169        /* free module object */
170        os_memoryFree (pRxQueue->hOs, pRxQueue, sizeof(TRxQueue));
171
172        return TI_OK;
173    }
174
175    return TI_NOK;
176}
177
178
179/**
180 * \fn     RxQueue_Init()
181 * \brief  Init required handles
182 *
183 * Init required handles and module variables.
184 *
185 * \note
186 * \param  hRxQueue - The module object
187 * \param  hReport - Report module Handles
188 * \return TI_OK on success or TI_NOK on failure
189 * \sa
190 */
191TI_STATUS RxQueue_Init (TI_HANDLE hRxQueue, TI_HANDLE hReport, TI_HANDLE hTimerModule)
192{
193	TRxQueue *pRxQueue = (TRxQueue *)hRxQueue;
194
195    pRxQueue->hReport   = hReport;
196
197	pRxQueue->hTimer = tmr_CreateTimer (hTimerModule);
198
199	return TI_OK;
200}
201
202
203/**
204 * \fn     RxQueue_Register_CB()
205 * \brief  Register the function to be called for received Rx.
206 *
207 * \note
208 * \param  hRxQueue - The module object
209 * \param  CallBackID - event ID
210 * \param  CBFunc - function address.
211 * \param  CBObj - function parameter.
212 * \return TI_OK on success or TI_NOK on failure
213 * \sa
214 */
215void RxQueue_Register_CB (TI_HANDLE hRxQueue, TI_UINT32 uCallBackID, void *CBFunc, TI_HANDLE CBObj)
216{
217    TRxQueue* pRxQueue = (TRxQueue *)hRxQueue;
218
219    TRACE1(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION , "RxQueue_Register_CB: CallBack ID = 0x%x\n", uCallBackID);
220
221    switch(uCallBackID)
222    {
223    case TWD_INT_RECEIVE_PACKET:
224        pRxQueue->tReceivePacketCB = (TPacketReceiveCb)CBFunc;
225        pRxQueue->hReceivePacketCB_handle = CBObj;
226        break;
227
228    default:
229        TRACE0(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_Register_CB: Illegal value\n");
230        break;
231    }
232}
233
234/**
235 * \fn     RxQueue_CloseBaSession ()
236 * \brief  Close BA session receiver and pass all packets in the TID queue to upper layer.
237 *
238 * \note
239 * \param  hRxQueue - RxQueue handle.
240 * \param  uFrameTid - TID session.
241 * \return None
242 * \sa
243 */
244void RxQueue_CloseBaSession(TI_HANDLE hRxQueue, TI_UINT8 uFrameTid)
245{
246    TRxQueue            *pRxQueue     = (TRxQueue *)hRxQueue;
247    TI_UINT32            i;
248    /*set the SA Tid pointer */
249    TRxQueueTidDataBase *pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]);
250
251    /* TID illegal value ? */
252    if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS)
253    {
254        TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_CloseBaSession: BA event - DELBA frame with TID value too big, TID = %d\n", uFrameTid);
255
256        return;
257    }
258
259    if(pTidDataBase->aTidBaEstablished == TI_TRUE)
260    {
261        /* clean BA session */
262        pTidDataBase->aTidBaEstablished = TI_FALSE;
263
264        /* pass all valid entries at the array */
265        for (i = 0; (i < RX_QUEUE_ARRAY_SIZE) && (i < RX_QUEUE_WIN_SIZE); i++)
266        {
267            if (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL)
268            {
269                RxQueue_PassPacket (pRxQueue,
270                                    pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus,
271                                    pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket);
272
273                pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL;
274
275                pRxQueue->tPacketTimeout.aPacketsStored--;
276            }
277
278            pTidDataBase->aWinStartArrayInex ++;
279
280            /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
281            pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
282        }
283
284        if (pRxQueue->tPacketTimeout.bPacketMiss)
285        {
286                tmr_StopTimer (pRxQueue->hTimer);
287                pRxQueue->tPacketTimeout.bPacketMiss = TI_FALSE;
288        }
289    }
290}
291
292
293/**
294 * \fn     RxQueue_PassPacket()
295 * \brief  Responsible on decode packet parameters and pass it to upper layer.
296 *
297 * \note
298 * \param  hRxQueue - RxQueue handle.
299 * \param  aStatus - RxXfer status that indicate if the upper layer should free the packet or use it.
300 * \param  pFrame - paket address of the packet
301 * \param  pRxParams - address to structure of the Rx Descriptor received by FW.
302 * \return TI_OK on success or TI_NOK on failure
303 * \sa
304 */
305static TI_STATUS RxQueue_PassPacket (TI_HANDLE hRxQueue, TI_STATUS tStatus, const void *pBuffer)
306{
307
308    TRxQueue            *pRxQueue   = (TRxQueue *)hRxQueue;
309
310    if (tStatus == TI_OK)
311    {
312        /* Get the mac header location in the packet Buffer */
313        dot11_header_t *pMacHdr = (dot11_header_t *)(TI_UINT8*)RX_BUF_DATA(pBuffer);
314
315        /* Handle endian for the frame control fields */
316        pMacHdr->fc  = ENDIAN_HANDLE_WORD(pMacHdr->fc);
317        pMacHdr->duration = ENDIAN_HANDLE_WORD(pMacHdr->duration);
318        pMacHdr->seqCtrl = ENDIAN_HANDLE_WORD(pMacHdr->seqCtrl);
319    }
320    else
321    {
322        RxIfDescriptor_t    *pRxParams  = (RxIfDescriptor_t*)pBuffer;
323
324        pRxParams->status &= ~RX_DESC_STATUS_MASK;
325        pRxParams->status |= RX_DESC_STATUS_DRIVER_RX_Q_FAIL;
326    }
327
328    TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION , "RxQueue_PassPacket: call TWD_OWNER_RX_QUEUE CB. In std rxData_ReceivePacket()\n");
329
330    /* Set the packet to upper layer */
331    /* if the packet status not success it will be discarded */
332    pRxQueue->tReceivePacketCB (pRxQueue->hReceivePacketCB_handle, pBuffer);
333
334    return TI_OK;
335}
336
337
338/**
339 * \fn     RxQueue_ReceivePacket()
340 * \brief  Main function of the RxQueue module.
341 * Responsible on reorder of the packets from the RxXfer to the RX module.
342 * Call from RxXfer in order to pass packet to uppers layers.
343 * In order to save disordered packets the module use array of structures per TID
344 * that each entry describe a packet. The array elements is sorted in the way that
345 * the winStart array index represent always the winStart packet and the lowest SN.
346 * Each increment index represent index at the BA window. Array index winEnd  always
347 * represent winEnd packet. The indexes of winStart and winEnd handled in cyclic manner.
348 * The function functionality devided to parts:
349 *   Part 1:
350 * in case the modulo receive packet with SN equal to winStart:
351 * "	pass it to upper layers
352 * "	increases winStart and array index winStart
353 * "	validate that all sequential queue packet are pass to the upper layers.
354 *   Part 2:
355 * in case the modulo receive packet that SN between winStart to winEnd:
356 * "	Save it sorted at the array at index: Save index = ((SN - winStart) + index array winStart) % arraySize.
357 *   Part 3:
358 * in case the modulo receive packet that SN higher than winEnd:
359 * "	Update winStart and WinEnd.
360 * "	Save it sorted at the array in index winEnd index.
361 * "	Pass to the upper layers all packets at the array indexes from old winStart index to the updated winStart index.
362 *   Part 4 + 5:
363 * in case the modulo receive BA event packet:
364 * "	Update winStart and WinEnd
365 * "	Pass to the upper layers all packets at the array indexes from old winStart index to the updated winStart index.
366 * "	Free BA event packet via pass it to upper layers with error status.
367 *
368 * \note
369 * \param  hRxQueue - RxQueue handle.
370 * \param  aStatus - RxXfer status that indicate if the upper layer should free the packet or use it.
371 * \param  pBuffer - paket address of the packet
372 * \return None
373 * \sa
374 */
375void RxQueue_ReceivePacket (TI_HANDLE hRxQueue, const void * pBuffer)
376{
377    TRxQueue            *pRxQueue   = (TRxQueue *)hRxQueue;
378    RxIfDescriptor_t    *pRxParams  = (RxIfDescriptor_t*)pBuffer;
379    TI_UINT8            *pFrame     = RX_BUF_DATA((TI_UINT8 *)pBuffer);
380    TI_STATUS           tStatus     = TI_OK;
381    dot11_header_t      *pHdr       = (dot11_header_t *)pFrame;
382    TI_UINT16		    uQosControl;
383
384    COPY_WLAN_WORD(&uQosControl, &pHdr->qosControl); /* copy with endianess handling. */
385
386    TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: packet_class_tag = 0x%x(%d)",pRxParams->packet_class_tag,pRxParams->packet_class_tag);
387
388    /*
389     * Retrieving the TAG from the packet itself and not from the Rx Descriptor since by now it is not correct
390     * Note: in the DR TAG_CLASS_EAPOL packet handled as TAG_CLASS_QOS_DATA
391     */
392    if (IS_QOS_FRAME(*(TI_UINT16*)pFrame) && (pRxParams->packet_class_tag != TAG_CLASS_QOS_DATA) && (pRxParams->packet_class_tag != TAG_CLASS_AMSDU))
393	{
394        TRACE1(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: BAD CLASS TAG =0x%x from FW.\n", pRxParams->packet_class_tag);
395
396        /* Get AMSDU bit from frame */
397        if( uQosControl & DOT11_QOS_CONTROL_FIELD_A_MSDU_BITS)
398        {
399            pRxParams->packet_class_tag = TAG_CLASS_AMSDU;
400        }
401        else
402        {
403            pRxParams->packet_class_tag = TAG_CLASS_QOS_DATA;
404        }
405    }
406
407    /*
408     * packet doesn't need reorder ?
409     */
410    if ((pRxParams->packet_class_tag != TAG_CLASS_QOS_DATA) && (pRxParams->packet_class_tag != TAG_CLASS_BA_EVENT) && (pRxParams->packet_class_tag != TAG_CLASS_AMSDU))
411    {
412        TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: pass packet without reorder.\n");
413
414        RxQueue_PassPacket (pRxQueue, tStatus, pBuffer);
415
416        return;
417    }
418
419
420    /*
421     * pRxParams->type == TAG_CLASS_QOS_DATA ?
422     */
423    if ((pRxParams->packet_class_tag == TAG_CLASS_QOS_DATA) || (pRxParams->packet_class_tag == TAG_CLASS_AMSDU))
424    {
425        TI_UINT8            uFrameTid;
426        TI_UINT16           uFrameSn;
427        TI_UINT16		    uSequenceControl;
428        TRxQueueTidDataBase *pTidDataBase;
429
430        /* Get TID from frame */
431        uFrameTid = uQosControl & DOT11_QOS_CONTROL_FIELD_TID_BITS;
432
433        TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: QoS Packet received");
434        TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: uFrameTid = 0x%x(%d)",uFrameTid,uFrameTid);
435
436        /* TID illegal value ? */
437        if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS)
438        {
439            TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR, "RxQueue_ReceivePacket: TID value too big, TID = %d. packet discarded!\n",uFrameTid);
440
441            RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
442
443            return;
444        }
445
446        /* Set the SA Tid pointer */
447        pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]);
448
449        /* TID legal value */
450        /* Packet TID BA session not established ? */
451        if (pTidDataBase->aTidBaEstablished != TI_TRUE)
452        {
453            TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: pass packet without reorder.\n");
454
455            RxQueue_PassPacket (pRxQueue, tStatus, pBuffer);
456
457            return;
458        }
459
460        /* packet TID BA established */
461        /* Get Sequence Number from frame */
462        COPY_WLAN_WORD(&uSequenceControl, &pHdr->seqCtrl); /* copy with endianess handling. */
463        uFrameSn = (uSequenceControl & DOT11_SC_SEQ_NUM_MASK) >> 4;
464
465        TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: uFrameSn = 0x%x(%d)", uFrameSn, uFrameSn);
466        TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: aTidExpectedSn = 0x%x(%d)",pTidDataBase->aTidExpectedSn, pTidDataBase->aTidExpectedSn);
467
468        /*
469         * Note:
470         * The FW never sends packet, in establish TID BA, with SN less than ESN !!!
471         */
472
473        /* Part 1 - Frame Sequence Number is the expected one ? */
474        if (uFrameSn == pTidDataBase->aTidExpectedSn)
475        {
476            TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: frame Sequence Number == expected one Sequence Number.\n");
477
478			/* Stop timer in case that the expected SN received and timer was running */
479
480
481            /* If we wait for 2 consecutive packets we should not stop the timer - This is why we are checking after the while loop, if we have
482               more packets stored, and if we have, we start the timer again.
483            */
484            if (pRxQueue->tPacketTimeout.bPacketMiss)
485            {
486                tmr_StopTimer (pRxQueue->hTimer);
487                pRxQueue->tPacketTimeout.bPacketMiss = TI_FALSE;
488            }
489
490
491            /* Pass the packet */
492            RxQueue_PassPacket (pRxQueue, tStatus, pBuffer);
493
494            /* Increase expected SN to the next */
495            pTidDataBase->aTidExpectedSn++;
496            pTidDataBase->aTidExpectedSn &= 0xfff;  /* SN is 12 bits long */
497
498            /* Increase the ArrayInex to the next */
499            pTidDataBase->aWinStartArrayInex++;
500
501            /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
502            pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
503
504            /* Pass all saved queue packets with SN higher than the expected one */
505            while (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL)
506            {
507                TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: Pass all saved queue packets with SN higher than the expected one that was just received.");
508                TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: aTidExpectedSn = 0x%x(%d)", pTidDataBase->aTidExpectedSn, pTidDataBase->aTidExpectedSn);
509                TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: aWinStartArrayInex = 0x%x(%d)", pTidDataBase->aWinStartArrayInex, pTidDataBase->aWinStartArrayInex);
510
511                RxQueue_PassPacket (pRxQueue,
512                                    pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus,
513                                    pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket);
514
515                pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL;
516
517                pTidDataBase->aWinStartArrayInex++;
518
519                /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
520                pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
521
522                 pTidDataBase->aTidExpectedSn++;
523				 pTidDataBase->aTidExpectedSn &= 0xfff; /* SN is 12 bits long */
524
525				 /* Decrease the packets in queue */
526                pRxQueue->tPacketTimeout.aPacketsStored--;
527            }
528
529
530            /* aTidExpectedSn % 0xfff in order to tack care of wrap around */
531            pTidDataBase->aTidExpectedSn &= 0xfff;
532
533            /* If there are still packets stored in the queue - start timer */
534			if (pRxQueue->tPacketTimeout.aPacketsStored)
535            {
536                tmr_StartTimer (pRxQueue->hTimer, RxQueue_PacketTimeOut, pRxQueue, BA_SESSION_TIME_TO_SLEEP, TI_FALSE);
537
538                pRxQueue->tPacketTimeout.bPacketMiss = TI_TRUE;
539                pRxQueue->tPacketTimeout.aFrameTid   = uFrameTid;
540            }
541
542            return;
543        }
544
545        /* Frame Sequence Number is lower than Expected sequence number (ISN) ? */
546        if (! BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn, pTidDataBase->aTidExpectedSn))
547        {
548            /* WLAN_OS_REPORT(("%s: ERROR - SN=%u is less than ESN=%u\n", __FUNCTION__, uFrameSn, pTidDataBase->aTidExpectedSn)); */
549            TRACE0(pRxQueue->hReport, REPORT_SEVERITY_ERROR, "RxQueue_ReceivePacket: frame Sequence Number is lower than expected sequence number.\n");
550
551            RxQueue_PassPacket (pRxQueue, tStatus, pBuffer);
552
553            return;
554        }
555
556        /* Part 2 - Frame Sequence Number between winStart and winEnd ? */
557        if ((BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn, pTidDataBase->aTidExpectedSn)) &&
558            /* mean: uFrameSn <= pTidDataBase->aTidExpectedSn + pTidDataBase->aTidWinSize) */
559            ( ! BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn,(pTidDataBase->aTidExpectedSn + pTidDataBase->aTidWinSize - 1))))
560        {
561            TI_UINT16 uSaveIndex = pTidDataBase->aWinStartArrayInex + (TI_UINT16)((uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidExpectedSn) & SEQ_NUM_MASK);
562
563            /* uSaveIndex % RX_QUEUE_ARRAY_SIZE */
564            uSaveIndex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
565
566            TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: frame Sequence Number between winStart and winEnd.\n");
567            TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: uSaveIndex = 0x%x(%d)",uSaveIndex,uSaveIndex);
568
569            /* Before storing packet in queue, make sure the place in the queue is vacant */
570			if (pTidDataBase->aPaketsQueue[uSaveIndex].pPacket == NULL)
571			{
572                TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: Enter packet to Reorder Queue");
573
574                /* Store the packet in the queue */
575                pTidDataBase->aPaketsQueue[uSaveIndex].tStatus  = tStatus;
576                pTidDataBase->aPaketsQueue[uSaveIndex].pPacket  = (void *)pBuffer;
577                pTidDataBase->aPaketsQueue[uSaveIndex].uFrameSn = uFrameSn;
578
579				pRxQueue->tPacketTimeout.aPacketsStored++;
580
581
582				/* Start Timer [only if timer is not already started - according to bPacketMiss] */
583                if(pRxQueue->tPacketTimeout.bPacketMiss == TI_FALSE)
584                {
585				    tmr_StartTimer (pRxQueue->hTimer, RxQueue_PacketTimeOut, pRxQueue, BA_SESSION_TIME_TO_SLEEP, TI_FALSE);
586				    pRxQueue->tPacketTimeout.bPacketMiss = TI_TRUE;
587				    pRxQueue->tPacketTimeout.aFrameTid   = uFrameTid;
588			    }
589            }
590			else
591			{
592 				 TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR, "RxQueue_ReceivePacket: frame Sequence has already saved. uFrameSn = %d\n", uFrameSn);
593
594				 RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
595				 return;
596			}
597            return;
598        }
599
600
601        /*
602        Part 3 - Frame Sequence Number higher than winEnd ?
603        */
604        if ( BA_SESSION_IS_A_BIGGER_THAN_B (uFrameSn, (pTidDataBase->aTidExpectedSn + pTidDataBase->aTidWinSize - 1)) )
605        {
606            TI_UINT32 i;
607            TI_UINT16 uNewWinStartSn = (uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidWinSize + 1) & SEQ_NUM_MASK;
608            TI_UINT16 uSaveIndex;
609
610
611			TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: frame Sequence Number higher than winEnd.\n");
612            TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: uNewWinStartSn = 0x%x(%d) STOP TIMER",uNewWinStartSn,uNewWinStartSn);
613
614            /* If timer is on - stop it */
615			if (pRxQueue->tPacketTimeout.bPacketMiss)
616            {
617                tmr_StopTimer (pRxQueue->hTimer);
618                pRxQueue->tPacketTimeout.bPacketMiss = TI_FALSE;
619            }
620
621            /* Increase the ArrayInex to the next */
622            pTidDataBase->aWinStartArrayInex++;
623
624            /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
625            pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
626
627            /* Update the Expected SN since the current one is lost */
628            pTidDataBase->aTidExpectedSn++;
629            pTidDataBase->aTidExpectedSn &= 0xFFF;
630
631            /* Pass all saved queue packets with SN lower than the new win start */
632            for (i = 0;
633                 BA_SESSION_IS_A_BIGGER_THAN_B(uNewWinStartSn,pTidDataBase->aTidExpectedSn) &&
634                  (i < RX_QUEUE_ARRAY_SIZE) &&
635                  (i < pTidDataBase->aTidWinSize);
636                 i++)
637            {
638                TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: aTidExpectedSn = 0x%x(%d)",pTidDataBase->aTidExpectedSn,pTidDataBase->aTidExpectedSn);
639                TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: aWinStartArrayInex = 0x%x(%d)",pTidDataBase->aWinStartArrayInex,pTidDataBase->aWinStartArrayInex);
640
641                if (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL)
642                {
643                    TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: Send Packet to Upper layer");
644                    RxQueue_PassPacket (pRxQueue,
645                                        pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus,
646                                        pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket);
647
648                    pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL;
649
650					pRxQueue->tPacketTimeout.aPacketsStored--;
651                }
652
653                pTidDataBase->aWinStartArrayInex++;
654
655                /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
656                pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
657
658                pTidDataBase->aTidExpectedSn++;
659                pTidDataBase->aTidExpectedSn &= 0xFFF;
660
661            }
662
663            TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: aTidExpectedSn = 0x%x(%d)",pTidDataBase->aTidExpectedSn,pTidDataBase->aTidExpectedSn);
664            TRACE1(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: i = %d",i);
665
666            /* Calculate the new Expected SN */
667            if (i == pTidDataBase->aTidWinSize)
668            {
669                TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: Set aTidExpectedSn to uNewWinStartSn");
670                pTidDataBase->aTidExpectedSn = uNewWinStartSn;
671            }
672            else
673            {
674                TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: Send all saved packets");
675                /* In case the uWinStartDelta lower than aTidWinSize check if ther are packets stored in Array */
676
677                while (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL)
678                {
679                    TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: Send packet with SN = 0x%x(%d)",pTidDataBase->aTidExpectedSn,pTidDataBase->aTidExpectedSn);
680
681                    RxQueue_PassPacket ( pRxQueue,
682                                         pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus,
683                                         pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket
684                                       );
685                    pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL;
686
687                    pTidDataBase->aWinStartArrayInex++;
688
689                    /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
690                    pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
691
692                    pTidDataBase->aTidExpectedSn++;
693                    pTidDataBase->aTidExpectedSn &= 0xFFF;
694
695                    pRxQueue->tPacketTimeout.aPacketsStored--;
696                }
697            }
698
699            TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: aTidExpectedSn = 0x%x(%d)",pTidDataBase->aTidExpectedSn,pTidDataBase->aTidExpectedSn);
700
701            if(pTidDataBase->aTidExpectedSn == uFrameSn)
702            {
703                TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: Send current packet to uper layer");
704                /* pass the packet */
705                RxQueue_PassPacket (pRxQueue, tStatus, pBuffer);
706                pTidDataBase->aTidExpectedSn++;
707				pTidDataBase->aTidExpectedSn &= 0xfff;
708            }
709            else
710            {
711                uSaveIndex = pTidDataBase->aWinStartArrayInex + (TI_UINT16)((uFrameSn + SEQ_NUM_WRAP - pTidDataBase->aTidExpectedSn) & SEQ_NUM_MASK);
712
713                TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: Enter current packet to Reorder Queue");
714                TRACE2(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: uSaveIndex = 0x%x(%d)", uSaveIndex, uSaveIndex);
715
716				/* uSaveIndex % RX_QUEUE_ARRAY_SIZE */
717				uSaveIndex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
718
719				/* Save the packet in the last entry of the queue */
720				pTidDataBase->aPaketsQueue[uSaveIndex].tStatus = tStatus;
721				pTidDataBase->aPaketsQueue[uSaveIndex].pPacket = (void *)pBuffer;
722				pTidDataBase->aPaketsQueue[uSaveIndex].pPacket = (void *)pBuffer;
723
724               pRxQueue->tPacketTimeout.aPacketsStored++;
725            }
726
727
728            /* aTidExpectedSn % 0xfff in order to tack care of wrap around */
729            pTidDataBase->aTidExpectedSn &= 0xfff;
730
731            /* If there are still packets stored in the queue - start timer */
732			if (pRxQueue->tPacketTimeout.aPacketsStored)
733            {
734                tmr_StartTimer (pRxQueue->hTimer, RxQueue_PacketTimeOut, pRxQueue, BA_SESSION_TIME_TO_SLEEP, TI_FALSE);
735                pRxQueue->tPacketTimeout.bPacketMiss = TI_TRUE;
736                pRxQueue->tPacketTimeout.aFrameTid   = uFrameTid;
737            }
738
739            return;
740        }
741    }
742
743
744    /*
745     * BA event ?
746     */
747    if (pRxParams->packet_class_tag == TAG_CLASS_BA_EVENT)
748    {
749        TRxQueueTidDataBase *pTidDataBase;
750        TI_UINT8            *pDataFrameBody;
751        TI_UINT16           ufc;
752        TI_UINT8            uFrameTid;
753        TI_UINT16           uStartingSequenceNumber;
754        TI_UINT16           uWinStartDelta;
755        TI_UINT16           uBarControlField;
756        TI_UINT16           uBaStartingSequenceControlField;
757        TI_UINT16           uBAParameterField;
758        TI_UINT32           i;
759
760        /* Get sub type from frame */
761        COPY_WLAN_WORD(&ufc, &pHdr->fc); /* copy with endianess handling. */
762
763        /* get the type to BA event */
764        switch ((dot11_Fc_Sub_Type_e)(ufc & DOT11_FC_SUB_MASK))
765        {
766        case DOT11_FC_SUB_BAR:
767            TRACE0(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION , "RxQueue_ReceivePacket: BA event - BAR frame.\n");
768
769            /* get pointer to the frame body */
770            pDataFrameBody = pFrame + sizeof(dot11_BarFrameHeader_t);
771
772            /* Get TID from BAR frame */
773            COPY_WLAN_WORD (&uBarControlField, (TI_UINT16 *)pDataFrameBody); /* copy with endianess handling. */
774            uFrameTid = (uBarControlField & DOT11_BAR_CONTROL_FIELD_TID_BITS) >> 12;
775
776            /* TID illegal value ? */
777            if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS)
778            {
779                TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - BAR frame with TID value too big, TID = %d.\n",uFrameTid);
780
781                RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
782
783                return;
784            }
785
786            /* set the SA Tid pointer */
787            pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]);
788
789            /* TID legal value */
790            /* packet TID BA not established ? */
791            if (pTidDataBase->aTidBaEstablished != TI_TRUE)
792            {
793                TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - BAR frame for TID not established, TID = %d.\n",uFrameTid);
794
795                RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
796
797                return;
798            }
799
800            /* Get Starting Sequence number from BAR frame */
801            pDataFrameBody = pDataFrameBody + 2;
802            COPY_WLAN_WORD (&uBaStartingSequenceControlField, (TI_UINT16 *)pDataFrameBody); /* copy with endianess handling. */
803            uStartingSequenceNumber = (uBaStartingSequenceControlField & DOT11_SC_SEQ_NUM_MASK) >> 4;
804
805            /* Starting Sequence Number is higher than winStart ? */
806            if ( BA_SESSION_IS_A_BIGGER_THAN_B (uStartingSequenceNumber, pTidDataBase->aTidExpectedSn) )
807            {
808                uWinStartDelta = uStartingSequenceNumber - pTidDataBase->aTidExpectedSn;
809                if (pRxQueue->tPacketTimeout.bPacketMiss)
810                {
811                    tmr_StopTimer (pRxQueue->hTimer);
812                    pRxQueue->tPacketTimeout.bPacketMiss = TI_FALSE;
813                }
814
815                /* pass all saved queue packets with SN lower than the new win start */
816                for (i = 0;
817                     ((i < uWinStartDelta) || (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL)) &&
818                      (i < RX_QUEUE_ARRAY_SIZE) &&
819                      (i < RX_QUEUE_WIN_SIZE);
820                     i++)
821                {
822                    if (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL)
823                    {
824                        RxQueue_PassPacket (pRxQueue,
825                                            pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus,
826                                            pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket);
827
828                        pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL;
829                        pRxQueue->tPacketTimeout.aPacketsStored--;
830                    }
831
832                    pTidDataBase->aWinStartArrayInex++;
833
834                    /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
835                    pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
836                }
837
838                if (pRxQueue->tPacketTimeout.aPacketsStored)
839                {
840                    tmr_StartTimer (pRxQueue->hTimer, RxQueue_PacketTimeOut, pRxQueue, BA_SESSION_TIME_TO_SLEEP, TI_FALSE);
841                    pRxQueue->tPacketTimeout.bPacketMiss = TI_TRUE;
842                    pRxQueue->tPacketTimeout.aFrameTid = uFrameTid;
843                }
844
845
846                pTidDataBase->aTidExpectedSn = uStartingSequenceNumber;
847            }
848            break;
849
850
851        case DOT11_FC_SUB_ACTION:
852            /* get pointer to the frame body */
853            pDataFrameBody = pFrame + sizeof(dot11_mgmtHeader_t);
854
855            /* get Action field from BA action frame */
856            pDataFrameBody++;
857            switch(*pDataFrameBody)
858            {
859            case DOT11_BA_ACTION_ADDBA:
860
861
862                /* get TID field and winSize from ADDBA action frame */
863                pDataFrameBody = pDataFrameBody + 2;
864                COPY_WLAN_WORD(&uBAParameterField, (TI_UINT16 *)pDataFrameBody); /* copy with endianess handling. */
865                uFrameTid = (uBAParameterField & DOT11_BA_PARAMETER_SET_FIELD_TID_BITS) >> 2;
866
867                /* TID illegal value ? */
868                if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS)
869                {
870                    TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - ADDBA frame with TID value too big, TID = %d.\n",uFrameTid);
871
872                    RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
873
874                    return;
875                }
876
877                /*set the SA Tid pointer */
878                pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]);
879
880                /* TID legal value */
881                /* packet TID BA established ? */
882                if (pTidDataBase->aTidBaEstablished == TI_TRUE)
883                {
884                    TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - ADDBA frame for TID already established, TID = %d.\n",uFrameTid);
885
886                    RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
887
888                    return;
889                }
890
891                /* get winSize from ADDBA action frame */
892                pTidDataBase->aTidWinSize = (uBAParameterField & DOT11_BA_PARAMETER_SET_FIELD_WINSIZE_BITS) >> 6;
893
894                /* winSize illegal value ? */
895                if (pTidDataBase->aTidWinSize > RX_QUEUE_WIN_SIZE)
896                {
897                    /* In case the win Size is higher than 8 the driver and the FW set it to 8 and inform the AP in ADDBA respond */
898                    pTidDataBase->aTidWinSize = RX_QUEUE_WIN_SIZE;
899                }
900
901                /* packet TID BA not yet established and winSize legal */
902                /* establishe BA TID */
903                pTidDataBase->aTidBaEstablished = TI_TRUE;
904
905                /* get initial sequence number (ISN) from ADDBA action frame */
906                pDataFrameBody = pDataFrameBody + 4;
907                COPY_WLAN_WORD (&uStartingSequenceNumber, (TI_UINT16 *)pDataFrameBody); /* copy with endianess handling. */
908                pTidDataBase->aTidExpectedSn = (uStartingSequenceNumber & DOT11_SC_SEQ_NUM_MASK) >> 4;
909                pTidDataBase->aWinStartArrayInex = 0;
910                os_memoryZero (pRxQueue->hOs, pTidDataBase->aPaketsQueue, sizeof (TRxQueuePacketEntry) * RX_QUEUE_ARRAY_SIZE);
911                break;
912
913            case DOT11_BA_ACTION_DELBA:
914
915
916                /* get TID field and winSize from ADDBA action frame */
917                pDataFrameBody = pDataFrameBody + 1;
918                COPY_WLAN_WORD(&uBAParameterField, (TI_UINT16 *)pDataFrameBody); /* copy with endianess handling. */
919                uFrameTid = (uBAParameterField & DOT11_DELBA_PARAMETER_FIELD_TID_BITS) >> 12;
920
921                /* TID illegal value ? */
922                if (uFrameTid >= MAX_NUM_OF_802_1d_TAGS)
923                {
924                    TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - DELBA frame with TID value too big, TID = %d.\n",uFrameTid);
925
926                    RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
927
928                    return;
929                }
930
931                /*set the SA Tid pointer */
932                pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[uFrameTid]);
933
934                /* TID legal value */
935                /* packet TID BA not established ? */
936                if (pTidDataBase->aTidBaEstablished != TI_TRUE)
937                {
938                    TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event - DELBA frame for TID not established, TID = %d.\n",uFrameTid);
939
940                    RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
941
942                    return;
943                }
944
945                RxQueue_CloseBaSession(hRxQueue, uFrameTid);
946                break;
947
948            default:
949                TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event Action field from BA action frame illegal. action = 0x%x\n",*pDataFrameBody);
950
951                RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
952
953                return;
954            }
955            break;
956
957        default:
958            TRACE1(pRxQueue->hReport, REPORT_SEVERITY_ERROR , "RxQueue_ReceivePacket: BA event with Subtype illegal. Subtype = 0x%x\n",((ufc & DOT11_FC_SUB_MASK) >> 4));
959
960            RxQueue_PassPacket (pRxQueue, TI_NOK, pBuffer);
961
962            return;
963          }
964
965    }
966
967    TRACE1(pRxQueue->hReport, REPORT_SEVERITY_INFORMATION, "RxQueue_ReceivePacket: unknow type tag. tag = %d\n", pRxParams->packet_class_tag);
968
969    RxQueue_PassPacket (pRxQueue, tStatus, pBuffer);
970
971    return;
972}
973
974
975/*
976Function Name : RxQueue_PacketTimeOut
977
978Description   : This function sends all consecutive old packets stored in a specific TID queue to the upper layer.
979
980                This function is called on timer wake up.
981                [The timer is started when we have stored packets in the RxQueue].
982
983
984Parameters    : hRxQueue        - A handle to the RxQueue structure.
985                bTwdInitOccured - Not used.
986
987Returned Value: void
988*/
989static void RxQueue_PacketTimeOut (TI_HANDLE hRxQueue, TI_BOOL bTwdInitOccured)
990{
991    TRxQueue            *pRxQueue   = (TRxQueue *)hRxQueue;
992    TRxQueueTidDataBase *pTidDataBase;
993
994    pRxQueue->tPacketTimeout.bPacketMiss = TI_FALSE;
995
996    /* Set the SA Tid pointer */
997    pTidDataBase = &(pRxQueue->tRxQueueArraysMng.tSa1ArrayMng[pRxQueue->tPacketTimeout.aFrameTid]);
998
999
1000    if (pRxQueue->tPacketTimeout.aPacketsStored)
1001    {
1002
1003        /* Find the first stored packet */
1004        while (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket == NULL)
1005        {
1006            pTidDataBase->aWinStartArrayInex++;
1007
1008            /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
1009            pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
1010
1011            pTidDataBase->aTidExpectedSn++;
1012            pTidDataBase->aTidExpectedSn &= 0xFFF;
1013        }
1014
1015
1016        /* Send all packets in order */
1017        while ((pRxQueue->tPacketTimeout.aPacketsStored > 0) && (pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket != NULL))
1018        {
1019
1020            RxQueue_PassPacket (pRxQueue,
1021                                pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].tStatus,
1022                                pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket);
1023
1024            pTidDataBase->aPaketsQueue[pTidDataBase->aWinStartArrayInex].pPacket = NULL;
1025
1026            pTidDataBase->aWinStartArrayInex++;
1027
1028            /* aWinStartArrayInex % RX_QUEUE_ARRAY_SIZE */
1029            pTidDataBase->aWinStartArrayInex &= RX_QUEUE_ARRAY_SIZE_BIT_MASK;
1030
1031            pTidDataBase->aTidExpectedSn++;
1032            pTidDataBase->aTidExpectedSn &= 0xFFF;
1033
1034            pRxQueue->tPacketTimeout.aPacketsStored--;
1035
1036        }
1037    }
1038
1039    if (pRxQueue->tPacketTimeout.aPacketsStored)
1040    {
1041        tmr_StartTimer (pRxQueue->hTimer, RxQueue_PacketTimeOut, pRxQueue, BA_SESSION_TIME_TO_SLEEP, TI_FALSE);
1042        pRxQueue->tPacketTimeout.bPacketMiss = TI_TRUE;
1043    }
1044}
1045