Home | History | Annotate | Download | only in FW_Transfer
      1 /*
      2  * CmdMBox.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  CmdMBox.c
     36  *  \brief Handle the wlan hardware command mailbox
     37  *
     38  *  \see CmdMBox.h, CmdMBox_api.h, CmdQueue.c
     39  */
     40 
     41 #define __FILE_ID__  FILE_ID_101
     42 #include "tidef.h"
     43 #include "osApi.h"
     44 #include "timer.h"
     45 #include "report.h"
     46 #include "FwEvent_api.h"
     47 #include "CmdMBox_api.h"
     48 #include "CmdMBox.h"
     49 #include "CmdQueue_api.h"
     50 #include "TWDriverInternal.h"
     51 #include "TwIf.h"
     52 
     53 /*****************************************************************************
     54  **         Internal functions definitions                                  **
     55  *****************************************************************************/
     56 
     57 /*
     58  * \brief	Handle cmdMbox timeout.
     59  *
     60  * \param  hCmdMbox  - Handle to CmdMbox
     61  * \return TI_OK
     62  *
     63  * \par Description
     64  * Call fErrorCb() to handle the error.
     65  *
     66  * \sa cmdMbox_SendCommand
     67  */
     68 static void cmdMbox_TimeOut (TI_HANDLE hCmdMbox, TI_BOOL bTwdInitOccured);
     69 static void cmdMbox_ConfigHwCb (TI_HANDLE hCmdMbox, TTxnStruct *pTxn);
     70 
     71 /*
     72  * \brief	Create the mailbox object
     73  *
     74  * \param  hOs  - OS module object handle
     75  * \return Handle to the created object
     76  *
     77  * \par Description
     78  * Calling this function creates a CmdMbox object
     79  *
     80  * \sa cmdMbox_Destroy
     81  */
     82 TI_HANDLE cmdMbox_Create (TI_HANDLE hOs)
     83 {
     84     TCmdMbox   *pCmdMbox;
     85 
     86     pCmdMbox = os_memoryAlloc (hOs, sizeof (TCmdMbox));
     87     if (pCmdMbox == NULL)
     88     {
     89         WLAN_OS_REPORT (("FATAL ERROR: cmdMbox_Create(): Error Creating CmdMbox - Aborting\n"));
     90         return NULL;
     91     }
     92 
     93     /* reset control module control block */
     94     os_memoryZero (hOs, pCmdMbox, sizeof (TCmdMbox));
     95     pCmdMbox->hOs = hOs;
     96 
     97     return pCmdMbox;
     98 }
     99 
    100 
    101 /*
    102  * \brief	Destroys the mailbox object
    103  *
    104  * \param  hCmdMbox  - The object to free
    105  * \return TI_OK
    106  *
    107  * \par Description
    108  * Calling this function destroys a CmdMbox object
    109  *
    110  * \sa cmdMbox_Create
    111  */
    112 TI_STATUS cmdMbox_Destroy (TI_HANDLE hCmdMbox)
    113 {
    114     TCmdMbox   *pCmdMbox = (TCmdMbox *)hCmdMbox;
    115 
    116     /* free timer */
    117     if (pCmdMbox->hCmdMboxTimer)
    118     {
    119         tmr_DestroyTimer (pCmdMbox->hCmdMboxTimer);
    120     }
    121 
    122     /* free context */
    123     os_memoryFree (pCmdMbox->hOs, pCmdMbox, sizeof (TCmdMbox));
    124 
    125     return TI_OK;
    126 }
    127 
    128 
    129 /*
    130  * \brief	Configure the CmdMbox object
    131  *
    132  * \param  hCmdMbox  - Handle to CmdMbox
    133  * \param  hReport  - Handle to report module
    134  * \param  hTwIf  - Handle to TwIf
    135  * \param  hTimer  - Handle to os timer
    136  * \param  hCmdQueue  - Handle to CmdQueue
    137  * \param  fErrorCb  - Handle to error handling function
    138  * \return TI_OK on success or TI_NOK on failure
    139  *
    140  * \par Description
    141  *
    142  * \sa
    143  */
    144 TI_STATUS cmdMbox_Init (TI_HANDLE hCmdMbox,
    145                           TI_HANDLE             hReport,
    146                         TI_HANDLE hTwIf,
    147                           TI_HANDLE             hTimer,
    148                         TI_HANDLE hCmdQueue,
    149                           TCmdMboxErrorCb       fErrorCb)
    150 {
    151     TCmdMbox   *pCmdMbox = (TCmdMbox *)hCmdMbox;
    152 
    153     pCmdMbox->hCmdQueue = hCmdQueue;
    154     pCmdMbox->hTwIf = hTwIf;
    155     pCmdMbox->hReport = hReport;
    156 
    157     pCmdMbox->uFwAddr = 0;
    158     pCmdMbox->uReadLen = 0;
    159     pCmdMbox->uWriteLen = 0;
    160     pCmdMbox->bCmdInProgress = TI_FALSE;
    161     pCmdMbox->fErrorCb = fErrorCb;
    162 
    163 	/* allocate OS timer memory */
    164     pCmdMbox->hCmdMboxTimer = tmr_CreateTimer (hTimer);
    165 	if (pCmdMbox->hCmdMboxTimer == NULL)
    166 	{
    167         TRACE0(pCmdMbox->hReport, REPORT_SEVERITY_ERROR, "cmdMbox_Init(): Failed to create hCmdMboxTimer!\n");
    168 		return TI_NOK;
    169 	}
    170 
    171     return TI_OK;
    172 }
    173 
    174 
    175 /*
    176  * \brief	Send the Command to the Mailbox
    177  *
    178  * \param  hCmdMbox  - Handle to CmdMbox
    179  * \param  cmdType  -
    180  * \param  pParamsBuf  - The buffer that will be written to the mailbox
    181  * \param  uWriteLen  - Length of data to write to the mailbox
    182  * \param  uReadLen  - Length of data to read from the mailbox (when the result is received)
    183  * \return TI_PENDING
    184  *
    185  * \par Description
    186  * Copy the buffer given to a local struct, update the write & read lengths
    187  * and send to the FW's mailbox.
    188  *
    189  *       ------------------------------------------------------
    190  *      | CmdMbox Header | Cmd Header    | Command parameters |
    191  *      ------------------------------------------------------
    192  *      | ID   | Status  | Type | Length | Command parameters |
    193  *      ------------------------------------------------------
    194  *       16bit   16bit    16bit   16bit
    195  *
    196  * \sa cmdMbox_CommandComplete
    197  */
    198 TI_STATUS cmdMbox_SendCommand       (TI_HANDLE hCmdMbox, Command_e cmdType, TI_UINT8* pParamsBuf, TI_UINT32 uWriteLen, TI_UINT32 uReadLen)
    199 {
    200     TCmdMbox   *pCmdMbox = (TCmdMbox *)hCmdMbox;
    201     TTxnStruct *pCmdTxn = (TTxnStruct*)&pCmdMbox->aCmdTxn[0].tTxnStruct;
    202     TTxnStruct *pRegTxn = (TTxnStruct*)&pCmdMbox->aRegTxn[0].tTxnStruct;
    203     Command_t  *pCmd = (Command_t*)&pCmdMbox->aCmdTxn[0].tCmdMbox;
    204 
    205 
    206     if (pCmdMbox->bCmdInProgress)
    207     {
    208         TRACE0(pCmdMbox->hReport, REPORT_SEVERITY_ERROR, "cmdMbox_SendCommand(): Trying to send Cmd while other Cmd is still in progres!\n");
    209         return TI_NOK;
    210     }
    211 
    212     /* Add the CMDMBOX_HEADER_LEN to the read length, used when reading the result later on */
    213     pCmdMbox->uReadLen = uReadLen + CMDMBOX_HEADER_LEN;
    214     /* Prepare the Cmd Hw template */
    215     pCmd->cmdID = cmdType;
    216     pCmd->cmdStatus = TI_OK;
    217     os_memoryCopy (pCmdMbox->hOs, (void *)pCmd->parameters, (void *)pParamsBuf, uWriteLen);
    218 
    219     /* Add the CMDMBOX_HEADER_LEN to the write length */
    220     pCmdMbox->uWriteLen = uWriteLen + CMDMBOX_HEADER_LEN;
    221 
    222     /* Must make sure that the length is multiple of 32 bit */
    223     if (pCmdMbox->uWriteLen & 0x3)
    224     {
    225         TRACE1(pCmdMbox->hReport, REPORT_SEVERITY_WARNING, "cmdMbox_SendCommand(): Command length isn't 32bit aligned! CmdId=%d\n", pCmd->cmdID);
    226         pCmdMbox->uWriteLen = (pCmdMbox->uWriteLen + 4) & 0xFFFFFFFC;
    227     }
    228 
    229     /* no other command can start the send process  till bCmdInProgress will return to TI_FALSE*/
    230     pCmdMbox->bCmdInProgress = TI_TRUE;
    231 
    232     /* Build the command TxnStruct */
    233     TXN_PARAM_SET(pCmdTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR)
    234     BUILD_TTxnStruct(pCmdTxn, pCmdMbox->uFwAddr, pCmd, pCmdMbox->uWriteLen, NULL, NULL)
    235     /* Send the command */
    236     twIf_Transact(pCmdMbox->hTwIf, pCmdTxn);
    237 
    238     /* Build the trig TxnStruct */
    239     pCmdMbox->aRegTxn[0].uRegister = INTR_TRIG_CMD;
    240     TXN_PARAM_SET(pRegTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR)
    241     BUILD_TTxnStruct(pRegTxn, ACX_REG_INTERRUPT_TRIG, &(pCmdMbox->aRegTxn[0].uRegister), REGISTER_SIZE, NULL, NULL)
    242 
    243     /* start the CmdMbox timer */
    244     tmr_StartTimer (pCmdMbox->hCmdMboxTimer, cmdMbox_TimeOut, hCmdMbox, CMDMBOX_WAIT_TIMEOUT, TI_FALSE);
    245 
    246     /* Send the FW trigger */
    247     twIf_Transact(pCmdMbox->hTwIf, pRegTxn);
    248 
    249 
    250     return TXN_STATUS_PENDING;
    251 }
    252 
    253 
    254 /*
    255  * \brief	Read the command's result
    256  *
    257  * \param  hCmdMbox  - Handle to CmdMbox
    258  * \return void
    259  *
    260  * \par Description
    261  * This function is called from FwEvent module uppon receiving command complete interrupt.
    262  * It issues a read transaction from the mailbox with a CB.
    263  *
    264  * \sa cmdMbox_SendCommand, cmdMbox_TransferComplete
    265  */
    266 ETxnStatus cmdMbox_CommandComplete (TI_HANDLE hCmdMbox)
    267 {
    268     TCmdMbox   *pCmdMbox = (TCmdMbox *)hCmdMbox;
    269     TTxnStruct *pCmdTxn = (TTxnStruct*)&pCmdMbox->aCmdTxn[1].tTxnStruct;
    270     Command_t  *pCmd = (Command_t*)&pCmdMbox->aCmdTxn[1].tCmdMbox;
    271     ETxnStatus  rc;
    272 
    273     /* stop the CmdMbox timer */
    274     tmr_StopTimer(pCmdMbox->hCmdMboxTimer);
    275 
    276     /* Build the command TxnStruct */
    277     TXN_PARAM_SET(pCmdTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_READ, TXN_INC_ADDR)
    278     /* Applying a CB in case of an async read */
    279     BUILD_TTxnStruct(pCmdTxn, pCmdMbox->uFwAddr, pCmd, pCmdMbox->uReadLen,(TTxnDoneCb)cmdMbox_TransferComplete, hCmdMbox)
    280     /* Send the command */
    281     rc = twIf_Transact(pCmdMbox->hTwIf, pCmdTxn);
    282 
    283     /* In case of a sync read, call the CB directly */
    284     if (rc == TXN_STATUS_COMPLETE)
    285     {
    286         cmdMbox_TransferComplete(hCmdMbox);
    287     }
    288 
    289     return TXN_STATUS_COMPLETE;
    290 }
    291 
    292 
    293 /*
    294  * \brief	Calls the cmdQueue_ResultReceived.
    295  *
    296  * \param  hCmdMbox  - Handle to CmdMbox
    297  * \return TI_OK
    298  *
    299  * \par Description
    300  * This function is called from cmdMbox_CommandComplete on a sync read, or from TwIf as a CB on an async read.
    301  * It calls cmdQueue_ResultReceived to continue the result handling procces & switch the bCmdInProgress flag to TI_FALSE,
    302  * meaning other commands can be sent to the FW.
    303  *
    304  * \sa cmdMbox_SendCommand, cmdMbox_TransferComplete
    305  */
    306 TI_STATUS cmdMbox_TransferComplete(TI_HANDLE hCmdMbox)
    307 {
    308     TCmdMbox   *pCmdMbox = (TCmdMbox *)hCmdMbox;
    309 
    310     /* Other commands can be sent to the FW */
    311     pCmdMbox->bCmdInProgress = TI_FALSE;
    312 
    313     cmdQueue_ResultReceived(pCmdMbox->hCmdQueue);
    314 
    315     return TI_OK;
    316 }
    317 
    318 
    319 /*
    320  * \brief	Handle cmdMbox timeout.
    321  *
    322  * \param  hCmdMbox  - Handle to CmdMbox
    323  * \return TI_OK
    324  *
    325  * \par Description
    326  * Call fErrorCb() to handle the error.
    327  *
    328  * \sa cmdMbox_SendCommand
    329  */
    330 static void cmdMbox_TimeOut (TI_HANDLE hCmdMbox, TI_BOOL bTwdInitOccured)
    331 {
    332     TCmdMbox   *pCmdMbox = (TCmdMbox *)hCmdMbox;
    333     Command_t  *pCmd = (Command_t*)&pCmdMbox->aCmdTxn[0].tCmdMbox;
    334 
    335     TRACE0(pCmdMbox->hReport, REPORT_SEVERITY_ERROR , "cmdMbox_TimeOut: Timeout occured in CmdMbox\n");
    336 
    337     /* Call error CB */
    338     if (pCmdMbox->fErrorCb != NULL)
    339     {
    340         pCmdMbox->fErrorCb (pCmdMbox->hCmdQueue,
    341                             (TI_UINT32)pCmd->cmdID,
    342                             CMD_STATUS_TIMEOUT,
    343                             (void *)pCmd->parameters);
    344     }
    345 }
    346 
    347 
    348 /*
    349  * \brief	configure the mailbox address.
    350  *
    351  * \param  hCmdMbox  - Handle to CmdMbox
    352  * \param  fCb  - Pointer to the CB
    353  * \param  hCb  - Cb's handle
    354  * \return TI_OK or TI_PENDING
    355  *
    356  * \par Description
    357  * Called from HwInit to read the command mailbox address.
    358  *
    359  * \sa
    360  */
    361 TI_STATUS cmdMbox_ConfigHw (TI_HANDLE hCmdMbox, fnotify_t fCb, TI_HANDLE hCb)
    362 {
    363     TCmdMbox   *pCmdMbox = (TCmdMbox *)hCmdMbox;
    364     TTxnStruct *pRegTxn = (TTxnStruct*)&pCmdMbox->aRegTxn[1].tTxnStruct;
    365     TI_STATUS   rc;
    366 
    367     pCmdMbox->fCb = fCb;
    368     pCmdMbox->hCb = hCb;
    369     /* Build the command TxnStruct */
    370     TXN_PARAM_SET(pRegTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_READ, TXN_INC_ADDR)
    371     BUILD_TTxnStruct(pRegTxn, REG_COMMAND_MAILBOX_PTR, &(pCmdMbox->aRegTxn[1].uRegister), REGISTER_SIZE,(TTxnDoneCb)cmdMbox_ConfigHwCb, hCmdMbox)
    372     /* Get the command mailbox address */
    373     rc = twIf_Transact(pCmdMbox->hTwIf, pRegTxn);
    374     if (rc == TXN_STATUS_COMPLETE)
    375     {
    376         pCmdMbox->uFwAddr = pCmdMbox->aRegTxn[1].uRegister;
    377     }
    378 
    379     return rc;
    380 }
    381 
    382 
    383 /*
    384  * \brief	Cb to cmdMbox_ConfigHw
    385  *
    386  * \param  hCmdMbox  - Handle to CmdMbox
    387  * \return TI_OK
    388  *
    389  * \par Description
    390  *
    391  * \sa
    392  */
    393 static void cmdMbox_ConfigHwCb (TI_HANDLE hCmdMbox, TTxnStruct *pTxn)
    394 {
    395     TCmdMbox   *pCmdMbox = (TCmdMbox *)hCmdMbox;
    396 
    397     pCmdMbox->uFwAddr = pCmdMbox->aRegTxn[1].uRegister;
    398 
    399     /* Call back the original State Machine */
    400     pCmdMbox->fCb(pCmdMbox->hCb, TI_OK);
    401 }
    402 
    403 
    404 /*
    405  * \brief	Restart the module upon driver stop or restart
    406  *
    407  * \param  hCmdMbox  - Handle to CmdMbox
    408  * \return TI_OK
    409  *
    410  * \par Description
    411  *
    412  * \sa
    413  */
    414 TI_STATUS cmdMbox_Restart (TI_HANDLE hCmdMbox)
    415 {
    416     TCmdMbox   *pCmdMbox = (TCmdMbox *)hCmdMbox;
    417 
    418     /* Stop the timeout timer if running and reset the state */
    419     tmr_StopTimer (pCmdMbox->hCmdMboxTimer);
    420     pCmdMbox->bCmdInProgress = TI_FALSE;
    421     pCmdMbox->uReadLen       = 0;
    422     pCmdMbox->uWriteLen      = 0;
    423 
    424     return TI_OK;
    425 }
    426 
    427 
    428 /*
    429  * \brief	Return the latest command status
    430  *
    431  * \param  hCmdMbox  - Handle to CmdMbox
    432  * \return TI_OK or TI_NOK
    433  *
    434  * \par Description
    435  *
    436  * \sa
    437  */
    438 TI_STATUS cmdMbox_GetStatus (TI_HANDLE hCmdMbox, CommandStatus_e *cmdStatus)
    439 {
    440     TCmdMbox   *pCmdMbox = (TCmdMbox *)hCmdMbox;
    441     Command_t  *pCmd = (Command_t*)&pCmdMbox->aCmdTxn[1].tCmdMbox;
    442     TI_STATUS   status;
    443 
    444     status = (pCmd->cmdStatus == CMD_STATUS_SUCCESS) ? TI_OK : TI_NOK;
    445     TRACE2(pCmdMbox->hReport, REPORT_SEVERITY_INFORMATION , "cmdMbox_GetStatus: TI_STATUS = (%d) <= pCmdMbox->tCmdMbox.cmdStatus = %d\n", status, pCmd->cmdStatus);
    446     *cmdStatus = pCmd->cmdStatus;
    447     return status;
    448 }
    449 
    450 /*
    451  * \brief	Return the MBox address
    452  *
    453  * \param  hCmdMbox  - Handle to CmdMbox
    454  * \return MBox address
    455  *
    456  * \par Description
    457  *
    458  * \sa
    459  */
    460 TI_UINT32 cmdMbox_GetMboxAddress (TI_HANDLE hCmdMbox)
    461 {
    462     TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
    463 
    464     return pCmdMbox->uFwAddr;
    465 }
    466 
    467 
    468 /*
    469  * \brief	Return the Command parameters buffer
    470  *
    471  * \param  hCmdMbox  - Handle to CmdMbox
    472  * \param  pParamBuf  - Holds the returned buffer
    473  * \return
    474  *
    475  * \par Description
    476  * Copying the command's data to pParamBuf
    477  *
    478  * \sa
    479  */
    480 void cmdMbox_GetCmdParams (TI_HANDLE hCmdMbox, TI_UINT8* pParamBuf)
    481 {
    482     TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
    483     Command_t  *pCmd = (Command_t*)&pCmdMbox->aCmdTxn[1].tCmdMbox;
    484 
    485     /*
    486      * Copy the results to the caller buffer:
    487      * We need to copy only the data without the cmdMbox header,
    488      * otherwise we will overflow the pParambuf
    489      */
    490     os_memoryCopy (pCmdMbox->hOs,
    491                    (void *)pParamBuf,
    492                    (void *)pCmd->parameters,
    493                    pCmdMbox->uReadLen - CMDMBOX_HEADER_LEN);
    494 
    495 }
    496 
    497 
    498 #ifdef TI_DBG
    499 
    500 void cmdMbox_PrintInfo(TI_HANDLE hCmdMbox)
    501 {
    502 #ifdef REPORT_LOG
    503     TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
    504 
    505     WLAN_OS_REPORT(("Print cmdMbox module info\n"));
    506     WLAN_OS_REPORT(("=========================\n"));
    507     WLAN_OS_REPORT(("bCmdInProgress = %d\n", pCmdMbox->bCmdInProgress));
    508 #endif
    509 }
    510 
    511 #endif  /* TI_DBG */
    512 
    513 
    514