1/*
2 * CmdQueue.c
3 *
4 * Copyright(c) 1998 - 2009 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  CmdQueue.c
36 *  \brief Handle the wlan command queue
37 *
38 *  \see CmdQueue.h, CmdQueue_api.h, CmdMBox.c
39 */
40
41
42#define __FILE_ID__  FILE_ID_97
43#include "tidef.h"
44#include "osApi.h"
45#include "report.h"
46#include "TwIf.h"
47#include "public_commands.h"
48#include "CmdQueue_api.h"
49#include "CmdMBox_api.h"
50#include "CmdQueue.h"
51
52/*****************************************************************************
53 **         Internal functions prototypes                                   **
54 *****************************************************************************/
55
56static TI_STATUS    cmdQueue_SM (TI_HANDLE hCmdQueue, ECmdQueueSmEvents event);
57static TI_STATUS    cmdQueue_Push (TI_HANDLE  hCmdQueue,
58                                   Command_e  cmdType,
59                                   TI_UINT8   *pParamsBuf,
60                                   TI_UINT32  uParamsLen,
61                                   void       *fCb,
62                                   TI_HANDLE  hCb,
63                                   void       *pCb);
64#ifdef TI_DBG
65static void         cmdQueue_PrintQueue(TCmdQueue  *pCmdQueue);
66#ifdef REPORT_LOG
67static char *       cmdQueue_GetIEString (TI_INT32 MboxCmdType, TI_UINT16 id);
68static char *       cmdQueue_GetCmdString (TI_INT32 MboxCmdType);
69#endif
70#endif /* TI_DBG */
71
72
73
74
75/*
76 * \brief	Create the TCmdQueue object
77 *
78 * \param  hOs  - OS module object handle
79 * \return Handle to the created object
80 *
81 * \par Description
82 * Calling this function creates a CmdQueue object
83 *
84 * \sa cmdQueue_Destroy
85 */
86TI_HANDLE cmdQueue_Create (TI_HANDLE hOs)
87{
88    TCmdQueue  *pCmdQueue;
89
90    pCmdQueue = os_memoryAlloc (hOs, sizeof(TCmdQueue));
91    if (pCmdQueue == NULL)
92    {
93        WLAN_OS_REPORT(("FATAL ERROR: cmdQueue_Create(): Error Creating aCmdQueue - Aborting\n"));
94        return NULL;
95    }
96
97    /* reset control module control block */
98    os_memoryZero (hOs, pCmdQueue, sizeof(TCmdQueue));
99    pCmdQueue->hOs = hOs;
100
101    return pCmdQueue;
102}
103
104
105/*
106 * \brief	Destroys the cmdQueue object
107 *
108 * \param  hCmdMbox  - The object to free
109 * \return TI_OK
110 *
111 * \par Description
112 * Calling this function destroys the cmdQueue object
113 *
114 * \sa cmdQueue_Create
115 */
116TI_STATUS cmdQueue_Destroy (TI_HANDLE hCmdQueue)
117{
118    TCmdQueue* pCmdQueue = (TCmdQueue*)hCmdQueue;
119
120    /* Free context */
121    os_memoryFree (pCmdQueue->hOs, pCmdQueue, sizeof(TCmdQueue));
122
123	return TI_OK;
124}
125
126
127/*
128 * \brief	Configure the CmdQueue object
129 *
130 * \param  hCmdQueue - Handle to CmdQueue
131 * \param  hCmdMbox  - Handle to CmdMbox
132 * \param  hReport - Handle to report module
133 * \param  hTwIf  - Handle to TwIf
134 * \param  hTimer  - Handle to os timer
135 * \return TI_OK on success or TI_NOK on failure
136 *
137 * \par Description
138 *
139 * \sa
140 */
141TI_STATUS cmdQueue_Init   (TI_HANDLE hCmdQueue,
142                           TI_HANDLE hCmdMbox,
143                           TI_HANDLE hReport,
144                           TI_HANDLE hTwIf,
145                           TI_HANDLE hTimer)
146{
147    TCmdQueue* pCmdQueue = (TCmdQueue*) hCmdQueue;
148
149    pCmdQueue->head = 0;
150    pCmdQueue->tail = 0;
151    pCmdQueue->uNumberOfCommandInQueue = 0;
152    pCmdQueue->uMaxNumberOfCommandInQueue = 0;
153    pCmdQueue->state = CMDQUEUE_STATE_IDLE;
154    pCmdQueue->fCmdCompleteCb = NULL;
155    pCmdQueue->hCmdCompleteCb = NULL;
156    pCmdQueue->fFailureCb = NULL;
157    pCmdQueue->hFailureCb = NULL;
158    pCmdQueue->hReport = hReport;
159    pCmdQueue->hCmdMBox = hCmdMbox;
160    pCmdQueue->hTwIf = hTwIf;
161    pCmdQueue->bErrorFlag = TI_FALSE;
162    pCmdQueue->bMboxEnabled = TI_FALSE;
163    pCmdQueue->bAwake = TI_FALSE;
164
165    /* Configure Command Mailbox */
166    cmdMbox_Init (hCmdMbox, hReport, hTwIf,
167                  hTimer, hCmdQueue,
168                  cmdQueue_Error);
169
170    /*
171     * NOTE: don't set uNumberOfRecoveryNodes = 0;
172     *       its value is used by recovery process
173     */
174
175    return TI_OK;
176}
177
178
179/*
180 * \brief	Configure the CmdQueue object
181 *
182 * \param  hCmdQueue - Handle to CmdQueue
183 * \param  eCmdQueueEvent - The event that triggered the SM
184 * \return TI_OK on success or TI_NOK on failure
185 *
186 * \par Description
187 * Handles the CmdQueue SM.
188 *
189 * \sa cmdQueue_Push, cmdQueue_ResultReceived
190 */
191static TI_STATUS cmdQueue_SM (TI_HANDLE hCmdQueue, ECmdQueueSmEvents eCmdQueueEvent)
192{
193    TCmdQueue     *pCmdQueue = (TCmdQueue*)hCmdQueue;
194    TI_BOOL        bBreakWhile = TI_FALSE;
195    TI_STATUS      rc = TI_OK, status;
196    TCmdQueueNode *pHead;
197    TI_UINT32      uReadLen, uWriteLen;
198
199    while(!bBreakWhile)
200    {
201        switch (pCmdQueue->state)
202        {
203            case CMDQUEUE_STATE_IDLE:
204                switch(eCmdQueueEvent)
205                {
206                    case CMDQUEUE_EVENT_RUN:
207                        pCmdQueue->state = CMDQUEUE_STATE_WAIT_FOR_COMPLETION;
208
209                        pHead = &pCmdQueue->aCmdQueue[pCmdQueue->head];
210
211                        #ifdef CMDQUEUE_DEBUG_PRINT
212                        TRACE4(pCmdQueue->hReport, REPORT_SEVERITY_CONSOLE, "cmdQueue_SM: Send Cmd: CmdType = %d(%d) Len = %d, NumOfCmd = %d", pHead->cmdType, (pHead->aParamsBuf) ?  *(TI_UINT16 *)pHead->aParamsBuf:0, pHead->uParamsLen, pCmdQueue->uNumberOfCommandInQueue));
213
214                        WLAN_OS_REPORT(("cmdQueue_SM: Send Cmd: CmdType = %s(%s)\n"
215                                        "Len = %d, NumOfCmd = %d \n",
216                                        cmdQueue_GetCmdString(pHead->cmdType),
217                                        (pHead->aParamsBuf) ?  cmdQueue_GetIEString(pHead->cmdType,*(TI_UINT16 *)pHead->aParamsBuf):"",
218                                        pHead->uParamsLen, pCmdQueue->uNumberOfCommandInQueue));
219                        #endif
220
221                        #ifdef TI_DBG
222                            pCmdQueue->uCmdSendCounter++;
223                        #endif
224
225                        /*
226                         * if bAwake is true, then we reached here because there were more commands
227                         * in the queue after sending a previous command.
228                         * There is no need to send another awake command to TwIf.
229                         */
230                        if (pCmdQueue->bAwake == TI_FALSE)
231                        {
232                            /* Keep the device awake for the entire Cmd transaction */
233                            twIf_Awake(pCmdQueue->hTwIf);
234                            pCmdQueue->bAwake = TI_TRUE;
235                        }
236
237                        if (pHead->cmdType == CMD_INTERROGATE)
238                        {
239                            uWriteLen = CMDQUEUE_INFO_ELEM_HEADER_LEN;
240                            /* Will be updated by CmdMbox to count the status response */
241                            uReadLen = pHead->uParamsLen;
242                        }
243                        else if(pHead->cmdType == CMD_TEST)
244                        {
245                            /* CMD_TEST has configure & interrogate abillities together */
246                            uWriteLen = pHead->uParamsLen;
247                            /* Will be updated by CmdMbox to count the status response */
248                            uReadLen = pHead->uParamsLen;
249                        }
250                        else /* CMD_CONFIGURE or others */
251                        {
252                            uWriteLen = pHead->uParamsLen;
253                            /* Will be updated by CmdMbox to count the status response */
254                            uReadLen = 0;
255
256                        }
257                        /* send the command to TNET */
258                        rc = cmdMbox_SendCommand (pCmdQueue->hCmdMBox,
259                                              pHead->cmdType,
260                                              pHead->aParamsBuf,
261                                              uWriteLen,
262                                              uReadLen);
263
264                        bBreakWhile = TI_TRUE;
265
266                        /* end of CMDQUEUE_EVENT_RUN */
267                        break;
268
269                    default:
270                        TRACE1(pCmdQueue->hReport, REPORT_SEVERITY_ERROR, "cmdQueue_SM: ** ERROR **  No such event (%d) for state CMDQUEUE_STATE_IDLE\n",eCmdQueueEvent);
271                        bBreakWhile = TI_TRUE;
272                        rc =  TI_NOK;
273
274                        break;
275                }
276                break;
277
278            case CMDQUEUE_STATE_WAIT_FOR_COMPLETION:
279                switch(eCmdQueueEvent)
280                {
281                    case CMDQUEUE_EVENT_RUN:
282                        /* We are in the middle of other command transaction so there is nothing top be done */
283                        bBreakWhile = TI_TRUE;
284                        rc = TXN_STATUS_PENDING;
285                        break;
286
287                    case CMDQUEUE_EVENT_COMPLETE:
288                        {
289                            Command_e cmdType;
290                            TI_UINT16        uParam;
291                            void *fCb, *hCb, *pCb;
292                            CommandStatus_e cmdStatus;
293
294                            pHead = &pCmdQueue->aCmdQueue[pCmdQueue->head];
295
296                            /* Keep callback parameters in temporary variables */
297                            cmdType = pHead->cmdType;
298                            uParam  = *(TI_UINT16 *)pHead->aParamsBuf;
299                            fCb = pHead->fCb;
300                            hCb = pHead->hCb;
301                            pCb = pHead->pInterrogateBuf;
302
303                            /*
304                             * Delete the command from the queue before calling a callback
305                             * because there may be nested calls inside a callback
306                             */
307                            pCmdQueue->head ++;
308                            if (pCmdQueue->head >= CMDQUEUE_QUEUE_DEPTH)
309                                pCmdQueue->head = 0;
310                            pCmdQueue->uNumberOfCommandInQueue --;
311
312                        #ifdef TI_DBG
313                            pCmdQueue->uCmdCompltCounter++;
314                        #endif
315
316                            /* Read the latest command return status */
317                            status = cmdMbox_GetStatus (pCmdQueue->hCmdMBox, &cmdStatus);
318                            if (status != TI_OK)
319                            {
320                                if (cmdStatus == CMD_STATUS_REJECT_MEAS_SG_ACTIVE)
321                                {
322                                    /* return reject status in the callback */
323                                    status = SG_REJECT_MEAS_SG_ACTIVE;
324                                    pCmdQueue->bErrorFlag = TI_FALSE;
325                                }
326                                else
327                                {
328                                    WLAN_OS_REPORT(("cmdQueue_SM: ** ERROR **  Mbox status error %d, set bErrorFlag !!!!!\n", cmdStatus));
329                                    TRACE1(pCmdQueue->hReport, REPORT_SEVERITY_ERROR, "cmdQueue_SM: ** ERROR **  Mbox status error %d, set bErrorFlag !!!!!\n", cmdStatus);
330                                    pCmdQueue->bErrorFlag = TI_TRUE;
331                                }
332                            }
333                            else
334                            {
335                                pCmdQueue->bErrorFlag = TI_FALSE;
336                            }
337
338                            /* If the command had a CB, then call it with the proper results buffer */
339                            if (fCb)
340                            {
341                                if (pCb)
342                                {
343                                    /* If pInterrogateBuf isn't NULL we need to copy the results */
344                                    cmdMbox_GetCmdParams(pCmdQueue->hCmdMBox, pCb);
345                                    /* Call the CB with the result buffer and the returned status */
346                                    ((TCmdQueueInterrogateCb)fCb) (hCb, status, pCb);
347                                }
348                                else
349                                {
350                                    /* Call the CB with only the returned status */
351                                    ((TCmdQueueCb)fCb) (hCb, status);
352                                }
353                            }
354                            else
355                            {
356                                /* Call the generic callback */
357                                if (pCmdQueue->fCmdCompleteCb)
358                                {
359                                    pCmdQueue->fCmdCompleteCb (pCmdQueue->hCmdCompleteCb, cmdType, uParam, status);
360                                }
361                            }
362
363                            /* Check if there are any more commands in queue */
364                            if (pCmdQueue->uNumberOfCommandInQueue > 0)
365                            {
366                                /* If queue isn't empty, send the next command */
367                                pCmdQueue->state = CMDQUEUE_STATE_IDLE;
368                                eCmdQueueEvent = CMDQUEUE_EVENT_RUN;
369                            }
370                            else
371                            {
372                                /* If queue is empty, we can permit TwIf to send sleep a command if neccesary */
373                                twIf_Sleep(pCmdQueue->hTwIf);
374                                pCmdQueue->bAwake = TI_FALSE;
375                                pCmdQueue->state = CMDQUEUE_STATE_IDLE;
376
377                                bBreakWhile = TI_TRUE;
378                            }
379                        /* end of CMDQUEUE_EVENT_COMPLETE */
380                        }
381                        break;
382
383                    default:
384                        TRACE1(pCmdQueue->hReport, REPORT_SEVERITY_ERROR, "cmdQueue_SM: ** ERROR **  No such event (%d) for state CMDQUEUE_STATE_IDLE\n",eCmdQueueEvent);
385                        bBreakWhile = TI_TRUE;
386                        rc =  TI_NOK;
387
388                        break;
389
390                /* end of switch event */
391                }
392                break;
393        /* end of switch state */
394        }
395    /* end of while */
396    }
397
398    return rc;
399}
400
401
402/*
403 * \brief	Sends the command to the cmdMbox
404 *
405 * \param  hCmdQueue - Handle to CmdQueue
406 * \param  eMboxCmdType - The command type
407 * \param  pMboxBuf - The command itself (parameters)
408 * \param  uParamsLen - The command's length
409 * \param  fCb - The command's Cb function
410 * \param  hCb - The command's Cb handle
411 * \param  pCb - Pointer to the results buffer (for interrogate commands)
412 * \return TI_OK on success or TI_NOK on failure
413 *
414 * \par Description
415 * Pushes the command to the command queue, which triggers the
416 * CmdQueue SM.
417 *
418 * \sa cmdQueue_Push
419 */
420TI_STATUS cmdQueue_SendCommand (TI_HANDLE  hCmdQueue,
421                            Command_e  eMboxCmdType,
422                            void      *pMboxBuf,
423                            TI_UINT32  uParamsLen,
424                            void      *fCb,
425                            TI_HANDLE  hCb,
426                            void      *pCb)
427{
428    TCmdQueue *pCmdQueue = (TCmdQueue*)hCmdQueue;
429    TI_STATUS  status;
430
431    if (pCmdQueue->bErrorFlag)
432        return TI_NOK;
433
434    status = cmdQueue_Push (pCmdQueue,
435                            eMboxCmdType,
436                            (TI_UINT8*)pMboxBuf,
437                            uParamsLen,
438                            fCb,
439                            hCb,
440                            (TI_UINT8*)pCb);
441
442    return RC_CONVERT (status);
443}
444
445
446/*
447 * \brief	Push the command Node to the Queue with its information element parameter
448 *
449 * \param  hCmdQueue - Handle to CmdQueue
450 * \param  cmdType - The command type
451 * \param  pParamsBuf - The command itself (parameters)
452 * \param  uParamsLen - The command's length
453 * \param  fCb - The command's Cb function
454 * \param  hCb - The command's Cb handle
455 * \param  pCb - Pointer to the results buffer (for interrogate commands)
456 * \return TI_OK on success or TI_NOK on failure
457 *
458 * \par Description
459 *
460 * \sa cmdQueue_SendCommand, cmdQueue_SM
461 */
462static TI_STATUS cmdQueue_Push (TI_HANDLE  hCmdQueue,
463                         Command_e  cmdType,
464                         TI_UINT8   *pParamsBuf,
465                         TI_UINT32  uParamsLen,
466                         void       *fCb,
467                         TI_HANDLE  hCb,
468                         void       *pCb)
469{
470    TCmdQueue *pCmdQueue = (TCmdQueue*)hCmdQueue;
471
472    /* If command type is NOT CMD_INTERROGATE, enter Push only if Mailbox is enabled */
473    if (!pCmdQueue->bMboxEnabled)
474        return TI_OK;
475
476    #ifdef TI_DBG
477        /*
478         * Check if Queue is Full
479         */
480        if (pCmdQueue->uNumberOfCommandInQueue == CMDQUEUE_QUEUE_DEPTH)
481        	{
482        TRACE0(pCmdQueue->hReport, REPORT_SEVERITY_ERROR, "cmdQueue_Push: ** ERROR ** The Queue is full\n");
483
484            	return  TI_NOK;
485        	}
486    #endif /* TI_DBG*/
487
488    /* Initializes the last Node in the Queue with the arrgs */
489    pCmdQueue->aCmdQueue[pCmdQueue->tail].cmdType   = cmdType;
490    pCmdQueue->aCmdQueue[pCmdQueue->tail].uParamsLen = uParamsLen;
491    pCmdQueue->aCmdQueue[pCmdQueue->tail].fCb = fCb;
492    pCmdQueue->aCmdQueue[pCmdQueue->tail].hCb = hCb;
493
494    os_memoryCopy (pCmdQueue->hOs,
495                   pCmdQueue->aCmdQueue[pCmdQueue->tail].aParamsBuf,
496                   pParamsBuf,
497                   uParamsLen);
498
499    pCmdQueue->aCmdQueue[pCmdQueue->tail].pInterrogateBuf = (TI_UINT8 *)pCb;
500
501    /* Advance the queue tail*/
502    pCmdQueue->tail++;
503    if (pCmdQueue->tail == CMDQUEUE_QUEUE_DEPTH)
504        pCmdQueue->tail = 0;
505
506    /* Update counters */
507    pCmdQueue->uNumberOfCommandInQueue++;
508
509    #ifdef TI_DBG
510        if (pCmdQueue->uMaxNumberOfCommandInQueue < pCmdQueue->uNumberOfCommandInQueue)
511        {
512            pCmdQueue->uMaxNumberOfCommandInQueue = pCmdQueue->uNumberOfCommandInQueue;
513        }
514    #endif /* TI_DBG*/
515
516    #ifdef CMDQUEUE_DEBUG_PRINT
517        WLAN_OS_REPORT(("cmdQueue_Push: CmdType = %s (%s(%d))"
518    			"Len = %d, NumOfCmd = %d \n",
519    			cmdQueue_GetCmdString(cmdType),
520    			(pParamsBuf) ?  cmdQueue_GetIEString(cmdType,*(TI_UINT16 *)pParamsBuf):"",
521    			(pParamsBuf) ?  *(TI_UINT16 *)pParamsBuf:0,
522                uParamsLen, pCmdQueue->uNumberOfCommandInQueue));
523    #endif
524
525    /* If queue has only one command trigger the send command from queue */
526    if (pCmdQueue->uNumberOfCommandInQueue == 1)
527	{
528        return cmdQueue_SM (pCmdQueue, CMDQUEUE_EVENT_RUN);
529	}
530	else
531    {
532        return TI_OK;
533    }
534}
535
536
537/*
538 * \brief	Notify the CmdQueue SM on the result received.
539 *
540 * \param  hCmdQueue - Handle to CmdQueue
541 * \return TI_OK on success or TI_NOK on failure
542 *
543 * \par Description
544 * Call the CmdQueue SM with CMDQUEUE_EVENT_COMPLETE
545 *
546 * \sa cmdQueue_SM
547 */
548TI_STATUS  cmdQueue_ResultReceived(TI_HANDLE hCmdQueue)
549{
550    TCmdQueue *pCmdQueue = (TCmdQueue*)hCmdQueue;
551
552    return cmdQueue_SM (pCmdQueue, CMDQUEUE_EVENT_COMPLETE);
553}
554
555
556/*
557 * \brief	Prepere the command queue for recovery.
558 *
559 * \param  hCmdQueue - Handle to CmdQueue
560 * \return TI_OK
561 *
562 * \par Description
563 * Copy the queue nodes to a recovery list, in order handle
564 * the commands CB's after recovery has finished
565 *
566 * \sa cmdQueue_EndReconfig
567 */
568TI_STATUS cmdQueue_Restart (TI_HANDLE hCmdQueue)
569{
570    TCmdQueue* pCmdQueue = (TCmdQueue*)   hCmdQueue;
571    TI_UINT32  uCurrentCmdIndex;
572    TI_UINT32  first  = pCmdQueue->head;
573    TCmdQueueNode *pHead;
574    TCmdQueueRecoveryNode *pRecoveryNode;
575
576    /*
577     * Stop the SM
578    */
579    pCmdQueue->state = CMDQUEUE_STATE_IDLE;
580    pCmdQueue->bAwake = TI_FALSE;
581
582TRACE0(pCmdQueue->hReport, REPORT_SEVERITY_INFORMATION, "cmdQueue_Clean: Cleaning aCmdQueue Queue");
583
584	/*
585     * Save The Call Back Function in the Queue in order the return them after the recovery
586     * with an error status
587	*/
588
589	/* Clean The Command Call Back Counter */
590    pCmdQueue->uNumberOfRecoveryNodes = 0;
591    pRecoveryNode = &pCmdQueue->aRecoveryQueue[pCmdQueue->uNumberOfRecoveryNodes];
592
593    for (uCurrentCmdIndex = 0;
594         uCurrentCmdIndex < pCmdQueue->uNumberOfCommandInQueue;
595         uCurrentCmdIndex++)
596    {
597        pHead  =  &pCmdQueue->aCmdQueue[first];
598
599        if (pHead->fCb != NULL)
600        {
601            /*Copy the interrogate CB and the interrogate data buffer pointer */
602            pRecoveryNode->fCb = pHead->fCb;
603            pRecoveryNode->hCb = pHead->hCb;
604            pRecoveryNode->pInterrogateBuf = pHead->pInterrogateBuf;
605            pCmdQueue->uNumberOfRecoveryNodes++;
606            pRecoveryNode = &pCmdQueue->aRecoveryQueue[pCmdQueue->uNumberOfRecoveryNodes];
607        }
608        first++;
609        if (first == CMDQUEUE_QUEUE_DEPTH)
610            first = 0;
611    }
612
613    /*
614     * Init the queue
615     */
616    pCmdQueue->head = 0;
617    pCmdQueue->tail = 0;
618    pCmdQueue->uNumberOfCommandInQueue = 0;
619
620    return TI_OK;
621}
622
623
624/*
625 * \brief	Call the stored CB to end the recovery of the MBox queue
626 *
627 * \param  hCmdQueue - Handle to CmdQueue
628 * \return TI_OK
629 *
630 * \par Description
631 * Call the stored CB's with an error status
632 *
633 * \sa cmdQueue_StartReconfig
634 */
635TI_STATUS cmdQueue_EndReconfig (TI_HANDLE hCmdQueue)
636{
637    TCmdQueue* pCmdQueue = (TCmdQueue*)   hCmdQueue;
638    TI_UINT32  uCbIndex;
639    TCmdQueueRecoveryNode *pHead;
640
641    for (uCbIndex = 0; uCbIndex < pCmdQueue->uNumberOfRecoveryNodes; uCbIndex++)
642    {
643        pHead  =  &pCmdQueue->aRecoveryQueue[uCbIndex];
644
645        if (pHead->pInterrogateBuf)
646        {
647            ((TCmdQueueInterrogateCb)pHead->fCb)(pHead->hCb, CMD_STATUS_FW_RESET, pHead->pInterrogateBuf);
648        }
649        else
650        {
651            ((TCmdQueueCb)pHead->fCb)(pHead->hCb, CMD_STATUS_FW_RESET);
652        }
653    }
654
655    pCmdQueue->uNumberOfRecoveryNodes = 0;
656
657	return TI_OK;
658}
659
660
661/*
662 * \brief	Register for a call back to be called when Command Complete occured and the CmdMboxCB was NULL
663 *
664 * \param  hCmdQueue - Handle to CmdQueue
665 * \param  fCb - The command's Cb function
666 * \param  hCb - The command's Cb handle
667 * \return TI_OK
668 *
669 * \par Description
670 *
671 * \sa
672 */
673TI_STATUS cmdQueue_RegisterCmdCompleteGenericCb (TI_HANDLE hCmdQueue, void *fCb, TI_HANDLE hCb)
674{
675    TCmdQueue* pCmdQueue = (TCmdQueue*)hCmdQueue;
676
677    if (fCb == NULL || hCb == NULL)
678	{
679TRACE0(pCmdQueue->hReport, REPORT_SEVERITY_ERROR, "cmdQueue_RegisterCmdCompleteGenericCB: NULL parameter\n");
680		return TI_NOK;
681	}
682
683    pCmdQueue->fCmdCompleteCb = (TCmdQueueGenericCb)fCb;
684    pCmdQueue->hCmdCompleteCb = hCb;
685
686	return TI_OK;
687}
688
689
690/*
691 * \brief	Register for a call back to be called when an Error (Timeout) occurs
692 *
693 * \param  hCmdQueue - Handle to CmdQueue
694 * \param  fCb - The command's Cb function
695 * \param  hCb - The command's Cb handle
696 * \return TI_OK
697 *
698 * \par Description
699 *
700 * \sa
701 */
702TI_STATUS cmdQueue_RegisterForErrorCb (TI_HANDLE hCmdQueue, void *fCb, TI_HANDLE hCb)
703{
704    TCmdQueue* pCmdQueue = (TCmdQueue*)hCmdQueue;
705
706    if (fCb == NULL || hCb == NULL)
707	{
708TRACE0(pCmdQueue->hReport, REPORT_SEVERITY_ERROR, "cmdQueue_RegisterForErrorCB: NULL parameters\n");
709		return TI_NOK;
710	}
711
712    pCmdQueue->hFailureCb = hCb;
713    pCmdQueue->fFailureCb = (TCmdQueueCb)fCb;
714
715	return TI_OK;
716}
717
718
719/*
720 * \brief	Enables the CmdMbox (on exit from init mode)
721 *
722 * \param  hCmdQueue - Handle to CmdQueue
723 * \return TI_OK
724 *
725 * \par Description
726 *
727 * \sa cmdQueue_DisableMbox
728 */
729TI_STATUS cmdQueue_EnableMbox (TI_HANDLE hCmdQueue)
730{
731    TCmdQueue* pCmdQueue = (TCmdQueue*)hCmdQueue;
732
733    pCmdQueue->bMboxEnabled = TI_TRUE;
734
735    return TI_OK;
736}
737
738
739/*
740 * \brief	Disables the CmdMbox (when stopping the driver)
741 *
742 * \param  hCmdQueue - Handle to CmdQueue
743 * \return TI_OK
744 *
745 * \par Description
746 *
747 * \sa cmdQueue_EnableMbox
748 */
749TI_STATUS cmdQueue_DisableMbox (TI_HANDLE hCmdQueue)
750{
751    TCmdQueue* pCmdQueue = (TCmdQueue*)hCmdQueue;
752
753    pCmdQueue->bMboxEnabled = TI_FALSE;
754
755    return TI_OK;
756}
757
758
759/*
760 * \brief	Called when a command timeout occur
761 *
762 * \param  hCmdQueue - Handle to CmdQueue
763 * \return TI_OK
764 *
765 * \par Description
766 *
767 * \sa cmdQueue_Init, cmdMbox_TimeOut
768 */
769TI_STATUS cmdQueue_Error (TI_HANDLE hCmdQueue, TI_UINT32 command, TI_UINT32 status, void *param)
770{
771    TCmdQueue* pCmdQueue = (TCmdQueue*)hCmdQueue;
772
773    if (status == CMD_STATUS_UNKNOWN_CMD)
774    {
775        TRACE1(pCmdQueue->hReport, REPORT_SEVERITY_ERROR , "cmdQueue_Error: Unknown Cmd  (%d)\n", command);
776    }
777    else if (status == CMD_STATUS_UNKNOWN_IE)
778    {
779        TRACE4(pCmdQueue->hReport, REPORT_SEVERITY_CONSOLE,"cmdQueue_Error: Unknown IE, cmdType : %d (%d) IE: %d (%d)\n", command, command, (param) ? *(TI_UINT16 *) param : 0, *((TI_UINT16 *) param));
780
781        WLAN_OS_REPORT(("cmdQueue_Error: Unknown IE, cmdType : %s (%d) IE: %s (%d)\n",
782                        cmdQueue_GetCmdString (command),
783                        command,
784                        (param) ? cmdQueue_GetIEString (command, *((TI_UINT16 *) param)) : "",
785                        *((TI_UINT16 *) param)));
786    }
787    else
788    {
789        TRACE1(pCmdQueue->hReport, REPORT_SEVERITY_ERROR , "cmdQueue_Error: CmdMbox status is %d\n", status);
790    }
791
792    if (status != CMD_STATUS_UNKNOWN_CMD && status != CMD_STATUS_UNKNOWN_IE)
793    {
794#ifdef TI_DBG
795#ifdef REPORT_LOG
796        TCmdQueueNode* pHead = &pCmdQueue->aCmdQueue[pCmdQueue->head];
797        TI_UINT32 TimeStamp = os_timeStampMs(pCmdQueue->hOs);
798
799        WLAN_OS_REPORT(("cmdQueue_Error: **ERROR**  Command Occured \n"
800						 "                                        Cmd = %s %s, Len = %d \n"
801						 "                                        NumOfCmd = %d\n"
802						 "                                        MAC TimeStamp on timeout = %d\n",
803						cmdQueue_GetCmdString(pHead->cmdType),
804						(pHead->aParamsBuf) ? cmdQueue_GetIEString(pHead->cmdType, *(TI_UINT16 *)pHead->aParamsBuf) : "",
805						pHead->uParamsLen,
806						pCmdQueue->uNumberOfCommandInQueue,
807						TimeStamp));
808#endif
809        /* Print The command that was sent before the timeout occur */
810        cmdQueue_PrintHistory(pCmdQueue, CMDQUEUE_HISTORY_DEPTH);
811
812#endif /* TI_DBG */
813
814        /* preform Recovery */
815        if (pCmdQueue->fFailureCb)
816        {
817            pCmdQueue->fFailureCb (pCmdQueue->hFailureCb, TI_NOK);
818        }
819    }
820
821    return TI_OK;
822}
823
824
825/*
826 * \brief	Returns maximum number of commands (ever) in TCmdQueue queue
827 *
828 * \param  hCmdQueue - Handle to CmdQueue
829 * \return maximum number of commands (ever) in mailbox queue
830 *
831 * \par Description
832 * Used for debugging purposes
833 *
834 * \sa cmdQueue_Error
835 */
836TI_UINT32 cmdQueue_GetMaxNumberOfCommands (TI_HANDLE hCmdQueue)
837{
838    TCmdQueue* pCmdQueue = (TCmdQueue*)hCmdQueue;
839
840    return pCmdQueue->uMaxNumberOfCommandInQueue;
841}
842
843
844
845/********************************************************************************
846*                              DEBUG  FUNCTIONS           	          			*
847*********************************************************************************/
848
849#ifdef TI_DBG
850
851/*
852 * \brief	Print the command queue & statistics
853 *
854 * \param  hCmdQueue - Handle to CmdQueue
855 * \return void
856 *
857 * \par Description
858 * Used for debugging purposes
859 *
860 * \sa cmdQueue_PrintQueue
861 */
862void cmdQueue_Print (TI_HANDLE hCmdQueue)
863{
864    TCmdQueue* pCmdQueue = (TCmdQueue*)hCmdQueue;
865
866    WLAN_OS_REPORT(("------------- aCmdQueue Queue -------------------\n"));
867
868    WLAN_OS_REPORT(("state = %d\n", pCmdQueue->state));
869    WLAN_OS_REPORT(("cmdQueue_Print:The Max NumOfCmd in Queue was = %d\n",
870                        pCmdQueue->uMaxNumberOfCommandInQueue));
871    WLAN_OS_REPORT(("cmdQueue_Print:The Current NumOfCmd in Queue = %d\n",
872                        pCmdQueue->uNumberOfCommandInQueue));
873    WLAN_OS_REPORT(("cmdQueue_Print:The Total number of Cmd send from Queue= %d\n",
874                        pCmdQueue->uCmdSendCounter));
875    WLAN_OS_REPORT(("cmdQueue_Print:The Total number of Cmd Completed interrupt= %d\n",
876                        pCmdQueue->uCmdCompltCounter));
877
878    cmdQueue_PrintQueue (pCmdQueue);
879}
880
881
882/*
883 * \brief	Print the command queue
884 *
885 * \param  pCmdQueue - Pointer to TCmdQueue
886 * \return void
887 *
888 * \par Description
889 * Used for debugging purposes
890 *
891 * \sa cmdQueue_Print, cmdQueue_GetCmdString, cmdQueue_GetIEString
892 */
893static void cmdQueue_PrintQueue (TCmdQueue *pCmdQueue)
894{
895    TI_UINT32 uCurrentCmdIndex;
896    TI_UINT32 first = pCmdQueue->head;
897    TCmdQueueNode* pHead;
898    TI_UINT32 NumberOfCommand = pCmdQueue->uNumberOfCommandInQueue;
899
900    for(uCurrentCmdIndex = 0 ; uCurrentCmdIndex < NumberOfCommand ; uCurrentCmdIndex++)
901    {
902        pHead = &pCmdQueue->aCmdQueue[first];
903
904        WLAN_OS_REPORT(("Cmd index %d CmdType = %s %s, Len = %d, Place in Queue = %d \n",
905                       uCurrentCmdIndex,
906                       cmdQueue_GetCmdString(pHead->cmdType),
907                       cmdQueue_GetIEString(pHead->cmdType, (((pHead->cmdType == CMD_INTERROGATE)||(pHead->cmdType == CMD_CONFIGURE)) ? *(TI_UINT16 *)pHead->aParamsBuf : 0)),
908                       pHead->uParamsLen,
909                       first));
910
911        first++;
912        if (first == CMDQUEUE_QUEUE_DEPTH)
913        {
914            first = 0;
915        }
916    }
917}
918
919
920/*
921 * \brief	print the last uNumOfCmd commands
922 *
923 * \param  hCmdQueue - Handle to CmdQueue
924 * \param  uNumOfCmd - Number of commands to print
925 * \return void
926 *
927 * \par Description
928 * Used for debugging purposes
929 *
930 * \sa cmdQueue_Error
931 */
932void cmdQueue_PrintHistory (TI_HANDLE hCmdQueue, TI_UINT32 uNumOfCmd)
933{
934#ifdef REPORT_LOG
935    TCmdQueue* pCmdQueue = (TCmdQueue*)hCmdQueue;
936    TI_UINT32 uCurrentCmdIndex;
937    TI_UINT32 first  = pCmdQueue->head;
938    TCmdQueueNode* pHead;
939
940    WLAN_OS_REPORT(("--------------- cmdQueue_PrintHistory of %d -------------------\n",uNumOfCmd));
941
942    for (uCurrentCmdIndex = 0; uCurrentCmdIndex < uNumOfCmd; uCurrentCmdIndex++)
943    {
944        pHead  =  &pCmdQueue->aCmdQueue[first];
945
946        WLAN_OS_REPORT(("Cmd index %d CmdType = %s %s, Len = %d, Place in Queue = %d \n",
947                        uCurrentCmdIndex,
948                        cmdQueue_GetCmdString(pHead->cmdType),
949                        cmdQueue_GetIEString(pHead->cmdType, (((pHead->cmdType == CMD_INTERROGATE)||(pHead->cmdType == CMD_CONFIGURE)) ? *(TI_UINT16 *)pHead->aParamsBuf : 0)),
950                        pHead->uParamsLen,
951                        first));
952
953        if (first == 0)
954        {
955            first = CMDQUEUE_QUEUE_DEPTH - 1;
956        }
957        else
958        {
959			first--;
960        }
961    }
962
963    WLAN_OS_REPORT(("-----------------------------------------------------------------------\n"));
964#endif
965}
966
967#ifdef REPORT_LOG
968/*
969 * \brief	Interperts the command's type to the command's name
970 *
971 * \param  MboxCmdType - The command type
972 * \return The command name
973 *
974 * \par Description
975 * Used for debugging purposes
976 *
977 * \sa
978 */
979static char* cmdQueue_GetCmdString (TI_INT32 MboxCmdType)
980    {
981    	switch (MboxCmdType)
982    	{
983    		case 0: return "CMD_RESET";
984    		case 1: return "CMD_INTERROGATE";
985    	 	case 2: return "CMD_CONFIGURE";
986    	    	case 3: return "CMD_ENABLE_RX";
987    		case 4: return "CMD_ENABLE_TX";
988    		case 5: return "CMD_DISABLE_RX";
989    	    	case 6: return "CMD_DISABLE_TX";
990    		case 8: return "CMD_SCAN";
991    		case 9: return "CMD_STOP_SCAN";
992    	    	case 10: return "CMD_VBM";
993    		case 11: return "CMD_START_JOIN";
994    		case 12: return "CMD_SET_KEYS";
995    		case 13: return "CMD_READ_MEMORY";
996    	    	case 14: return "CMD_WRITE_MEMORY";
997            case 19: return "CMD_SET_TEMPLATE";
998    		case 23: return "CMD_TEST";
999    		case 27: return "CMD_ENABLE_RX_PATH";
1000    		case 28: return "CMD_NOISE_HIST";
1001    	    	case 29: return "CMD_RX_RESET";
1002    		case 32: return "CMD_LNA_CONTROL";
1003    		case 33: return "CMD_SET_BCN_MODE";
1004    		case 34: return "CMD_MEASUREMENT";
1005    		case 35: return "CMD_STOP_MEASUREMENT";
1006    		case 36: return "CMD_DISCONNECT";
1007    		case 37: return "CMD_SET_PS_MODE";
1008    		case 38: return "CMD_CHANNEL_SWITCH";
1009    		case 39: return "CMD_STOP_CHANNEL_SWICTH";
1010    		case 40: return "CMD_AP_DISCOVERY";
1011    		case 41: return "CMD_STOP_AP_DISCOVERY";
1012    		case 42: return "CMD_SPS_SCAN";
1013    		case 43: return "CMD_STOP_SPS_SCAN";
1014            case 45: return "CMD_HEALTH_CHECK";
1015            case 48: return "CMD_CONNECTION_SCAN_CFG";
1016            case 49: return "CMD_CONNECTION_SCAN_SSID_CFG";
1017            case 50: return "CMD_START_PERIODIC_SCAN";
1018            case 51: return "CMD_STOP_PERIODIC_SCAN";
1019            case 52: return "CMD_SET_STATUS";
1020    		default: return " *** Error No Such CMD **** ";
1021    	}
1022    }
1023
1024/*
1025 * \brief	Interperts the command's IE to the command's IE name
1026 *
1027 * \param  MboxCmdType - The command IE number
1028 * \return The command IE name
1029 *
1030 * \par Description
1031 * Used for debugging purposes
1032 *
1033 * \sa
1034 */
1035static char * cmdQueue_GetIEString (TI_INT32 MboxCmdType, TI_UINT16 Id)
1036{
1037    if( MboxCmdType== CMD_INTERROGATE || MboxCmdType == CMD_CONFIGURE)
1038    {
1039        switch (Id)
1040        {
1041        case ACX_WAKE_UP_CONDITIONS: 		return " (ACX_WAKE_UP_CONDITIONS)";
1042        case ACX_MEM_CFG: 					return " (ACX_MEM_CFG)";
1043        case ACX_SLOT: 						return " (ACX_SLOT) ";
1044        case ACX_AC_CFG: 					return " (ACX_AC_CFG) ";
1045        case ACX_MEM_MAP: 					return " (ACX_MEM_MAP)";
1046        case ACX_AID: 						return " (ACX_AID)";
1047        case ACX_MEDIUM_USAGE: 				return " (ACX_MEDIUM_USAGE) ";
1048        case ACX_RX_CFG: 					return " (ACX_RX_CFG) ";
1049        case ACX_STATISTICS: 				return " (ACX_STATISTICS) ";
1050        case ACX_FEATURE_CFG: 				return " (ACX_FEATURE_CFG) ";
1051        case ACX_TID_CFG: 					return " (ACX_TID_CFG) ";
1052        case ACX_BEACON_FILTER_OPT: 		return " (ACX_BEACON_FILTER_OPT) ";
1053        case ACX_NOISE_HIST: 				return " (ACX_NOISE_HIST)";
1054        case ACX_PD_THRESHOLD: 				return " (ACX_PD_THRESHOLD) ";
1055        case ACX_TX_CONFIG_OPT: 			return " (ACX_TX_CONFIG_OPT) ";
1056        case ACX_CCA_THRESHOLD: 			return " (ACX_CCA_THRESHOLD)";
1057        case ACX_EVENT_MBOX_MASK: 			return " (ACX_EVENT_MBOX_MASK) ";
1058        case ACX_CONN_MONIT_PARAMS: 		return " (ACX_CONN_MONIT_PARAMS) ";
1059        case ACX_CONS_TX_FAILURE: 			return " (ACX_CONS_TX_FAILURE) ";
1060        case ACX_BCN_DTIM_OPTIONS: 			return " (ACX_BCN_DTIM_OPTIONS) ";
1061        case ACX_SG_ENABLE: 				return " (ACX_SG_ENABLE) ";
1062        case ACX_SG_CFG: 					return " (ACX_SG_CFG) ";
1063        case ACX_FM_COEX_CFG: 				return " (ACX_FM_COEX_CFG) ";
1064        case ACX_BEACON_FILTER_TABLE: 		return " (ACX_BEACON_FILTER_TABLE) ";
1065        case ACX_ARP_IP_FILTER: 			return " (ACX_ARP_IP_FILTER) ";
1066        case ACX_ROAMING_STATISTICS_TBL:	return " (ACX_ROAMING_STATISTICS_TBL) ";
1067        case ACX_RATE_POLICY: 				return " (ACX_RATE_POLICY) ";
1068        case ACX_CTS_PROTECTION: 			return " (ACX_CTS_PROTECTION) ";
1069        case ACX_SLEEP_AUTH: 				return " (ACX_SLEEP_AUTH) ";
1070        case ACX_PREAMBLE_TYPE: 			return " (ACX_PREAMBLE_TYPE) ";
1071        case ACX_ERROR_CNT: 				return " (ACX_ERROR_CNT) ";
1072        case ACX_IBSS_FILTER: 				return " (ACX_IBSS_FILTER) ";
1073        case ACX_SERVICE_PERIOD_TIMEOUT:	return " (ACX_SERVICE_PERIOD_TIMEOUT) ";
1074        case ACX_TSF_INFO: 					return " (ACX_TSF_INFO) ";
1075        case ACX_CONFIG_PS_WMM: 			return " (ACX_CONFIG_PS_WMM) ";
1076        case ACX_ENABLE_RX_DATA_FILTER: 	return " (ACX_ENABLE_RX_DATA_FILTER) ";
1077        case ACX_SET_RX_DATA_FILTER: 		return " (ACX_SET_RX_DATA_FILTER) ";
1078        case ACX_GET_DATA_FILTER_STATISTICS:return " (ACX_GET_DATA_FILTER_STATISTICS) ";
1079        case ACX_RX_CONFIG_OPT: 			return " (ACX_RX_CONFIG_OPT) ";
1080        case ACX_FRAG_CFG: 				    return " (ACX_FRAG_CFG) ";
1081        case ACX_BET_ENABLE: 				return " (ACX_BET_ENABLE) ";
1082        case ACX_RSSI_SNR_TRIGGER: 			return " (ACX_RSSI_SNR_TRIGGER) ";
1083        case ACX_RSSI_SNR_WEIGHTS: 			return " (ACX_RSSI_SNR_WEIGHTS) ";
1084        case ACX_KEEP_ALIVE_MODE:           return " (ACX_KEEP_ALIVE_MODE) ";
1085        case ACX_SET_KEEP_ALIVE_CONFIG:     return " (ACX_SET_KEEP_ALIVE_CONFIG) ";
1086        case DOT11_RX_MSDU_LIFE_TIME: 		return " (DOT11_RX_MSDU_LIFE_TIME) ";
1087        case DOT11_CUR_TX_PWR:   			return " (DOT11_CUR_TX_PWR) ";
1088        case DOT11_RTS_THRESHOLD: 			return " (DOT11_RTS_THRESHOLD) ";
1089        case DOT11_GROUP_ADDRESS_TBL: 		return " (DOT11_GROUP_ADDRESS_TBL) ";
1090
1091        default:	return " *** Error No Such IE **** ";
1092        }
1093    }
1094    return "";
1095}
1096#endif
1097#endif  /* TI_DBG */
1098
1099
1100