--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/TWD/FW_Transfer/CmdMBox.c Tue Jun 29 12:34:26 2010 +0100
@@ -0,0 +1,552 @@
+/*
+ * CmdMBox.c
+ *
+ * Copyright(c) 1998 - 2010 Texas Instruments. All rights reserved.
+ * All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 or BSD License which accompanies
+ * this distribution. The Eclipse Public License is available at
+ * http://www.eclipse.org/legal/epl-v10.html and the BSD License is as below.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Texas Instruments nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/** \file CmdMBox.c
+ * \brief Handle the wlan hardware command mailbox
+ *
+ * \see CmdMBox.h, CmdMBox_api.h, CmdQueue.c
+ */
+
+#define __FILE_ID__ FILE_ID_101
+#include "tidef.h"
+#include "osApi.h"
+#include "timer.h"
+#include "report.h"
+#include "FwEvent_api.h"
+#include "CmdMBox_api.h"
+#include "CmdMBox.h"
+#include "CmdQueue_api.h"
+#include "TWDriverInternal.h"
+#include "TwIf.h"
+
+/*****************************************************************************
+ ** Internal functions definitions **
+ *****************************************************************************/
+
+/*
+ * \brief Handle cmdMbox timeout.
+ *
+ * \param hCmdMbox - Handle to CmdMbox
+ * \return TI_OK
+ *
+ * \par Description
+ * Call fErrorCb() to handle the error.
+ *
+ * \sa cmdMbox_SendCommand
+ */
+static void cmdMbox_TimeOut (TI_HANDLE hCmdMbox, TI_BOOL bTwdInitOccured);
+static void cmdMbox_ConfigHwCb (TI_HANDLE hCmdMbox, TTxnStruct *pTxn);
+
+/*
+ * \brief Create the mailbox object
+ *
+ * \param hOs - OS module object handle
+ * \return Handle to the created object
+ *
+ * \par Description
+ * Calling this function creates a CmdMbox object
+ *
+ * \sa cmdMbox_Destroy
+ */
+TI_HANDLE cmdMbox_Create (TI_HANDLE hOs)
+{
+ TCmdMbox *pCmdMbox;
+ TI_UINT8 CMD;
+
+ pCmdMbox = os_memoryAlloc (hOs, sizeof (TCmdMbox),MemoryNormal);
+ if (pCmdMbox == NULL)
+ {
+ WLAN_OS_REPORT (("FATAL ERROR: cmdMbox_Create(): Error Creating CmdMbox - Aborting\n"));
+ return NULL;
+ }
+
+ /* reset control module control block */
+ os_memoryZero (hOs, pCmdMbox, sizeof (TCmdMbox));
+ pCmdMbox->hOs = hOs;
+
+ /* Allocate the CMD Mbox buffers and Registers buffers */
+ for (CMD = 0; CMD < CMD_NUM; CMD++)
+ {
+ /* MBOX */
+ pCmdMbox->aCmdTxn[CMD].pCmdMbox = os_memoryAlloc (hOs, sizeof (Command_t) + WSPI_PAD_LEN_READ,MemoryDMA);
+ if (pCmdMbox->aCmdTxn[CMD].pCmdMbox == NULL)
+ {
+ return NULL;
+ }
+ os_memoryZero (hOs, pCmdMbox->aCmdTxn[CMD].pCmdMbox, sizeof (Command_t) + WSPI_PAD_LEN_READ);
+ pCmdMbox->aCmdTxn[CMD].pCmdMbox += WSPI_PAD_LEN_READ;
+ /* Register */
+ pCmdMbox->aRegTxn[CMD].pRegister = os_memoryAlloc (hOs, sizeof (TI_UINT32) + WSPI_PAD_LEN_READ,MemoryDMA);
+ if (pCmdMbox->aRegTxn[CMD].pRegister == NULL)
+ {
+ return NULL;
+ }
+ os_memoryZero (hOs, pCmdMbox->aRegTxn[CMD].pRegister, sizeof (TI_UINT32) + WSPI_PAD_LEN_READ);
+ pCmdMbox->aRegTxn[CMD].pRegister += WSPI_PAD_LEN_READ;
+ }
+
+
+ return pCmdMbox;
+}
+
+
+/*
+ * \brief Destroys the mailbox object
+ *
+ * \param hCmdMbox - The object to free
+ * \return TI_OK
+ *
+ * \par Description
+ * Calling this function destroys a CmdMbox object
+ *
+ * \sa cmdMbox_Create
+ */
+TI_STATUS cmdMbox_Destroy (TI_HANDLE hCmdMbox)
+{
+ TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
+ TI_UINT8 CMD;
+
+ /* free timer */
+ if (pCmdMbox->hCmdMboxTimer)
+ {
+ tmr_DestroyTimer (pCmdMbox->hCmdMboxTimer);
+ }
+
+ /* Free MBOX and Registers buffers */
+ for (CMD = 0; CMD < CMD_NUM; CMD++)
+ {
+ if (pCmdMbox->aCmdTxn[CMD].pCmdMbox)
+ {
+ os_memoryFree (pCmdMbox->hOs, ((TI_UINT8*)(pCmdMbox->aCmdTxn[CMD].pCmdMbox)) - WSPI_PAD_LEN_READ, sizeof (Command_t) + WSPI_PAD_LEN_READ);
+ }
+ if (pCmdMbox->aRegTxn[CMD].pRegister)
+ {
+ os_memoryFree (pCmdMbox->hOs, pCmdMbox->aRegTxn[CMD].pRegister - WSPI_PAD_LEN_READ, sizeof (TI_UINT32) + WSPI_PAD_LEN_READ);
+ }
+ }
+
+ /* free context */
+ os_memoryFree (pCmdMbox->hOs, pCmdMbox, sizeof (TCmdMbox));
+
+ return TI_OK;
+}
+
+
+/*
+ * \brief Configure the CmdMbox object
+ *
+ * \param hCmdMbox - Handle to CmdMbox
+ * \param hReport - Handle to report module
+ * \param hTwIf - Handle to TwIf
+ * \param hTimer - Handle to os timer
+ * \param hCmdQueue - Handle to CmdQueue
+ * \param fErrorCb - Handle to error handling function
+ * \return TI_OK on success or TI_NOK on failure
+ *
+ * \par Description
+ *
+ * \sa
+ */
+TI_STATUS cmdMbox_Init (TI_HANDLE hCmdMbox,
+ TI_HANDLE hReport,
+ TI_HANDLE hTwIf,
+ TI_HANDLE hTimer,
+ TI_HANDLE hCmdQueue,
+ TCmdMboxErrorCb fErrorCb)
+{
+ TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
+
+ pCmdMbox->hCmdQueue = hCmdQueue;
+ pCmdMbox->hTwIf = hTwIf;
+ pCmdMbox->hReport = hReport;
+ pCmdMbox->hCmdMboxTimer = hTimer;
+
+ pCmdMbox->uFwAddr = 0;
+ pCmdMbox->uReadLen = 0;
+ pCmdMbox->uWriteLen = 0;
+ pCmdMbox->bCmdInProgress = TI_FALSE;
+ pCmdMbox->fErrorCb = fErrorCb;
+
+ /* allocate OS timer memory */
+ pCmdMbox->hCmdMboxTimer = tmr_CreateTimer (hTimer);
+ if (pCmdMbox->hCmdMboxTimer == NULL)
+ {
+ TRACE0(pCmdMbox->hReport, REPORT_SEVERITY_ERROR, "cmdMbox_Init(): Failed to create hCmdMboxTimer!\n");
+ return TI_NOK;
+ }
+
+ return TI_OK;
+}
+
+
+/*
+ * \brief Send the Command to the Mailbox
+ *
+ * \param hCmdMbox - Handle to CmdMbox
+ * \param cmdType -
+ * \param pParamsBuf - The buffer that will be written to the mailbox
+ * \param uWriteLen - Length of data to write to the mailbox
+ * \param uReadLen - Length of data to read from the mailbox (when the result is received)
+ * \return TI_PENDING
+ *
+ * \par Description
+ * Copy the buffer given to a local struct, update the write & read lengths
+ * and send to the FW's mailbox.
+ *
+ * ------------------------------------------------------
+ * | CmdMbox Header | Cmd Header | Command parameters |
+ * ------------------------------------------------------
+ * | ID | Status | Type | Length | Command parameters |
+ * ------------------------------------------------------
+ * 16bit 16bit 16bit 16bit
+ *
+ * \sa cmdMbox_CommandComplete
+ */
+TI_STATUS cmdMbox_SendCommand (TI_HANDLE hCmdMbox, Command_e cmdType, TI_UINT8* pParamsBuf, TI_UINT32 uWriteLen, TI_UINT32 uReadLen)
+{
+ TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
+ TTxnStruct *pCmdTxn = (TTxnStruct*)&pCmdMbox->aCmdTxn[0].tTxnStruct;
+ TTxnStruct *pRegTxn = (TTxnStruct*)&pCmdMbox->aRegTxn[0].tTxnStruct;
+ Command_t *pCmd = ((Command_t *)(pCmdMbox->aCmdTxn[0].pCmdMbox));
+
+
+ if (pCmdMbox->bCmdInProgress)
+ {
+ TRACE0(pCmdMbox->hReport, REPORT_SEVERITY_ERROR, "cmdMbox_SendCommand(): Trying to send Cmd while other Cmd is still in progres!\n");
+ return TI_NOK;
+ }
+
+ /* Add the CMDMBOX_HEADER_LEN to the read length, used when reading the result later on */
+ pCmdMbox->uReadLen = uReadLen + CMDMBOX_HEADER_LEN;
+ /* Prepare the Cmd Hw template */
+ pCmd->cmdID = cmdType;
+ pCmd->cmdStatus = TI_OK;
+ os_memoryCopy (pCmdMbox->hOs, (void *)pCmd->parameters, (void *)pParamsBuf, uWriteLen);
+
+ /* Add the CMDMBOX_HEADER_LEN to the write length */
+ pCmdMbox->uWriteLen = uWriteLen + CMDMBOX_HEADER_LEN;
+
+ /* Must make sure that the length is multiple of 32 bit */
+ if (pCmdMbox->uWriteLen & 0x3)
+ {
+ TRACE1(pCmdMbox->hReport, REPORT_SEVERITY_WARNING, "cmdMbox_SendCommand(): Command length isn't 32bit aligned! CmdId=%d\n", pCmd->cmdID);
+ pCmdMbox->uWriteLen = (pCmdMbox->uWriteLen + 4) & 0xFFFFFFFC;
+ }
+
+ /* no other command can start the send process till bCmdInProgress will return to TI_FALSE*/
+ pCmdMbox->bCmdInProgress = TI_TRUE;
+
+ /* Build the command TxnStruct */
+ TXN_PARAM_SET(pCmdTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR)
+ BUILD_TTxnStruct(pCmdTxn, pCmdMbox->uFwAddr, pCmd, pCmdMbox->uWriteLen, NULL, NULL)
+ /* Send the command */
+ twIf_Transact(pCmdMbox->hTwIf, pCmdTxn);
+
+ /* Build the trig TxnStruct */
+ *((TI_UINT32*)(pCmdMbox->aRegTxn[0].pRegister)) = INTR_TRIG_CMD;
+ TXN_PARAM_SET(pRegTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR)
+ BUILD_TTxnStruct(pRegTxn, ACX_REG_INTERRUPT_TRIG, pCmdMbox->aRegTxn[0].pRegister, REGISTER_SIZE, NULL, NULL)
+
+ /* start the CmdMbox timer */
+ tmr_StartTimer (pCmdMbox->hCmdMboxTimer, cmdMbox_TimeOut, hCmdMbox, CMDMBOX_WAIT_TIMEOUT, TI_FALSE);
+
+ /* Send the FW trigger */
+ twIf_Transact(pCmdMbox->hTwIf, pRegTxn);
+
+
+ return TXN_STATUS_PENDING;
+}
+
+
+/*
+ * \brief Read the command's result
+ *
+ * \param hCmdMbox - Handle to CmdMbox
+ * \return void
+ *
+ * \par Description
+ * This function is called from FwEvent module uppon receiving command complete interrupt.
+ * It issues a read transaction from the mailbox with a CB.
+ *
+ * \sa cmdMbox_SendCommand, cmdMbox_TransferComplete
+ */
+void cmdMbox_CommandComplete (TI_HANDLE hCmdMbox)
+{
+ TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
+ TTxnStruct *pCmdTxn = (TTxnStruct*)&pCmdMbox->aCmdTxn[1].tTxnStruct;
+ Command_t *pCmd = ((Command_t *)(pCmdMbox->aCmdTxn[1].pCmdMbox));
+ ETxnStatus rc;
+
+ /* stop the CmdMbox timer */
+ tmr_StopTimer(pCmdMbox->hCmdMboxTimer);
+
+ /* Build the command TxnStruct */
+ TXN_PARAM_SET(pCmdTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_READ, TXN_INC_ADDR)
+ /* Applying a CB in case of an async read */
+ BUILD_TTxnStruct(pCmdTxn, pCmdMbox->uFwAddr, pCmd, pCmdMbox->uReadLen,(TTxnDoneCb)cmdMbox_TransferComplete, hCmdMbox)
+ /* Send the command */
+ rc = twIf_Transact(pCmdMbox->hTwIf, pCmdTxn);
+
+ /* In case of a sync read, call the CB directly */
+ if (rc == TXN_STATUS_COMPLETE)
+ {
+ cmdMbox_TransferComplete(hCmdMbox);
+ }
+}
+
+
+/*
+ * \brief Calls the cmdQueue_ResultReceived.
+ *
+ * \param hCmdMbox - Handle to CmdMbox
+ * \return TI_OK
+ *
+ * \par Description
+ * This function is called from cmdMbox_CommandComplete on a sync read, or from TwIf as a CB on an async read.
+ * It calls cmdQueue_ResultReceived to continue the result handling procces & switch the bCmdInProgress flag to TI_FALSE,
+ * meaning other commands can be sent to the FW.
+ *
+ * \sa cmdMbox_SendCommand, cmdMbox_TransferComplete
+ */
+TI_STATUS cmdMbox_TransferComplete(TI_HANDLE hCmdMbox)
+{
+ TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
+
+ /* Other commands can be sent to the FW */
+ pCmdMbox->bCmdInProgress = TI_FALSE;
+
+ cmdQueue_ResultReceived(pCmdMbox->hCmdQueue);
+
+ return TI_OK;
+}
+
+
+/*
+ * \brief Handle cmdMbox timeout.
+ *
+ * \param hCmdMbox - Handle to CmdMbox
+ * \return TI_OK
+ *
+ * \par Description
+ * Call fErrorCb() to handle the error.
+ *
+ * \sa cmdMbox_SendCommand
+ */
+static void cmdMbox_TimeOut (TI_HANDLE hCmdMbox, TI_BOOL bTwdInitOccured)
+{
+ TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
+ Command_t *pCmd = ((Command_t *)(pCmdMbox->aCmdTxn[0].pCmdMbox));
+
+ TRACE0(pCmdMbox->hReport, REPORT_SEVERITY_ERROR , "cmdMbox_TimeOut: Timeout occured in CmdMbox\n");
+
+ /* Call error CB */
+ if (pCmdMbox->fErrorCb != NULL)
+ {
+ pCmdMbox->fErrorCb (pCmdMbox->hCmdQueue,
+ (TI_UINT32)pCmd->cmdID,
+ CMD_STATUS_TIMEOUT,
+ (void *)pCmd->parameters);
+ }
+}
+
+
+/*
+ * \brief configure the mailbox address.
+ *
+ * \param hCmdMbox - Handle to CmdMbox
+ * \param fCb - Pointer to the CB
+ * \param hCb - Cb's handle
+ * \return TI_OK or TI_PENDING
+ *
+ * \par Description
+ * Called from HwInit to read the command mailbox address.
+ *
+ * \sa
+ */
+TI_STATUS cmdMbox_ConfigHw (TI_HANDLE hCmdMbox, fnotify_t fCb, TI_HANDLE hCb)
+{
+ TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
+ TTxnStruct *pRegTxn = (TTxnStruct*)&pCmdMbox->aRegTxn[1].tTxnStruct;
+ TI_STATUS rc;
+
+ pCmdMbox->fCb = fCb;
+ pCmdMbox->hCb = hCb;
+ /* Build the command TxnStruct */
+ TXN_PARAM_SET(pRegTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_READ, TXN_INC_ADDR)
+ BUILD_TTxnStruct(pRegTxn, REG_COMMAND_MAILBOX_PTR, pCmdMbox->aRegTxn[1].pRegister, REGISTER_SIZE,(TTxnDoneCb)cmdMbox_ConfigHwCb, hCmdMbox)
+ /* Get the command mailbox address */
+ rc = twIf_Transact(pCmdMbox->hTwIf, pRegTxn);
+ if (rc == TXN_STATUS_COMPLETE)
+ {
+ pCmdMbox->uFwAddr = *((TI_UINT32 *)(pCmdMbox->aRegTxn[1].pRegister));
+ }
+
+ return rc;
+}
+
+
+/*
+ * \brief Cb to cmdMbox_ConfigHw
+ *
+ * \param hCmdMbox - Handle to CmdMbox
+ * \return TI_OK
+ *
+ * \par Description
+ *
+ * \sa
+ */
+static void cmdMbox_ConfigHwCb (TI_HANDLE hCmdMbox, TTxnStruct *pTxn)
+{
+ TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
+
+ pCmdMbox->uFwAddr = *((TI_UINT32 *)(pCmdMbox->aRegTxn[1].pRegister));
+
+ /* Call back the original State Machine */
+ pCmdMbox->fCb(pCmdMbox->hCb, TI_OK);
+}
+
+
+/*
+ * \brief Restart the module upon driver stop or restart
+ *
+ * \param hCmdMbox - Handle to CmdMbox
+ * \return TI_OK
+ *
+ * \par Description
+ *
+ * \sa
+ */
+TI_STATUS cmdMbox_Restart (TI_HANDLE hCmdMbox)
+{
+ TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
+
+ /* Stop the timeout timer if running and reset the state */
+ tmr_StopTimer (pCmdMbox->hCmdMboxTimer);
+ pCmdMbox->bCmdInProgress = TI_FALSE;
+ pCmdMbox->uReadLen = 0;
+ pCmdMbox->uWriteLen = 0;
+
+ return TI_OK;
+}
+
+
+/*
+ * \brief Return the latest command status
+ *
+ * \param hCmdMbox - Handle to CmdMbox
+ * \return TI_OK or TI_NOK
+ *
+ * \par Description
+ *
+ * \sa
+ */
+TI_STATUS cmdMbox_GetStatus (TI_HANDLE hCmdMbox)
+{
+ TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
+ Command_t *pCmd = ((Command_t *)(pCmdMbox->aCmdTxn[1].pCmdMbox));
+ TI_STATUS status;
+
+ status = (pCmd->cmdStatus == CMD_STATUS_SUCCESS) ? TI_OK : TI_NOK;
+ TRACE2(pCmdMbox->hReport, REPORT_SEVERITY_INFORMATION , "cmdMbox_GetStatus: TI_STATUS = (%d) <= pCmdMbox->pCmdMbox.cmdStatus = %d\n", status, pCmd->cmdStatus);
+ return status;
+}
+
+
+/*
+ * \brief Return the MBox address
+ *
+ * \param hCmdMbox - Handle to CmdMbox
+ * \return MBox address
+ *
+ * \par Description
+ *
+ * \sa
+ */
+TI_UINT32 cmdMbox_GetMboxAddress (TI_HANDLE hCmdMbox)
+{
+ TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
+
+ return pCmdMbox->uFwAddr;
+}
+
+
+/*
+ * \brief Return the Command parameters buffer
+ *
+ * \param hCmdMbox - Handle to CmdMbox
+ * \param pParamBuf - Holds the returned buffer
+ * \return
+ *
+ * \par Description
+ * Copying the command's data to pParamBuf
+ *
+ * \sa
+ */
+void cmdMbox_GetCmdParams (TI_HANDLE hCmdMbox, TI_UINT8* pParamBuf)
+{
+ TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
+ Command_t *pCmd = ((Command_t *)(pCmdMbox->aCmdTxn[1].pCmdMbox));
+
+ /*
+ * Copy the results to the caller buffer:
+ * We need to copy only the data without the cmdMbox header,
+ * otherwise we will overflow the pParambuf
+ */
+ os_memoryCopy (pCmdMbox->hOs,
+ (void *)pParamBuf,
+ (void *)pCmd->parameters,
+ pCmdMbox->uReadLen - CMDMBOX_HEADER_LEN);
+
+}
+
+
+#ifdef TI_DBG
+
+void cmdMbox_PrintInfo(TI_HANDLE hCmdMbox)
+{
+ TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
+
+ WLAN_OS_REPORT(("Print cmdMbox module info\n"));
+ WLAN_OS_REPORT(("=========================\n"));
+ WLAN_OS_REPORT(("bCmdInProgress = %d\n", pCmdMbox->bCmdInProgress));
+}
+
+#endif /* TI_DBG */
+
+