4 * Copyright(c) 1998 - 2010 Texas Instruments. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
36 * \brief Handle the wlan hardware command mailbox
38 * \see CmdMBox.h, CmdMBox_api.h, CmdQueue.c
41 #define __FILE_ID__ FILE_ID_101
46 #include "FwEvent_api.h"
47 #include "CmdMBox_api.h"
49 #include "CmdQueue_api.h"
50 #include "TWDriverInternal.h"
53 /*****************************************************************************
54 ** Internal functions definitions **
55 *****************************************************************************/
58 * \brief Handle cmdMbox timeout.
60 * \param hCmdMbox - Handle to CmdMbox
64 * Call fErrorCb() to handle the error.
66 * \sa cmdMbox_SendCommand
68 static void cmdMbox_TimeOut (TI_HANDLE hCmdMbox, TI_BOOL bTwdInitOccured);
69 static void cmdMbox_ConfigHwCb (TI_HANDLE hCmdMbox, TTxnStruct *pTxn);
72 * \brief Create the mailbox object
74 * \param hOs - OS module object handle
75 * \return Handle to the created object
78 * Calling this function creates a CmdMbox object
82 TI_HANDLE cmdMbox_Create (TI_HANDLE hOs)
86 pCmdMbox = os_memoryAlloc (hOs, sizeof (TCmdMbox));
89 WLAN_OS_REPORT (("FATAL ERROR: cmdMbox_Create(): Error Creating CmdMbox - Aborting\n"));
93 /* reset control module control block */
94 os_memoryZero (hOs, pCmdMbox, sizeof (TCmdMbox));
102 * \brief Destroys the mailbox object
104 * \param hCmdMbox - The object to free
108 * Calling this function destroys a CmdMbox object
112 TI_STATUS cmdMbox_Destroy (TI_HANDLE hCmdMbox)
114 TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
117 if (pCmdMbox->hCmdMboxTimer)
119 tmr_DestroyTimer (pCmdMbox->hCmdMboxTimer);
123 os_memoryFree (pCmdMbox->hOs, pCmdMbox, sizeof (TCmdMbox));
130 * \brief Configure the CmdMbox object
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
144 TI_STATUS cmdMbox_Init (TI_HANDLE hCmdMbox,
149 TCmdMboxErrorCb fErrorCb)
151 TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
153 pCmdMbox->hCmdQueue = hCmdQueue;
154 pCmdMbox->hTwIf = hTwIf;
155 pCmdMbox->hReport = hReport;
157 pCmdMbox->uFwAddr = 0;
158 pCmdMbox->uReadLen = 0;
159 pCmdMbox->uWriteLen = 0;
160 pCmdMbox->bCmdInProgress = TI_FALSE;
161 pCmdMbox->fErrorCb = fErrorCb;
163 /* allocate OS timer memory */
164 pCmdMbox->hCmdMboxTimer = tmr_CreateTimer (hTimer);
165 if (pCmdMbox->hCmdMboxTimer == NULL)
167 TRACE0(pCmdMbox->hReport, REPORT_SEVERITY_ERROR, "cmdMbox_Init(): Failed to create hCmdMboxTimer!\n");
176 * \brief Send the Command to the Mailbox
178 * \param hCmdMbox - Handle to CmdMbox
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)
186 * Copy the buffer given to a local struct, update the write & read lengths
187 * and send to the FW's mailbox.
189 * ------------------------------------------------------
190 * | CmdMbox Header | Cmd Header | Command parameters |
191 * ------------------------------------------------------
192 * | ID | Status | Type | Length | Command parameters |
193 * ------------------------------------------------------
194 * 16bit 16bit 16bit 16bit
196 * \sa cmdMbox_CommandComplete
198 TI_STATUS cmdMbox_SendCommand (TI_HANDLE hCmdMbox, Command_e cmdType, TI_UINT8* pParamsBuf, TI_UINT32 uWriteLen, TI_UINT32 uReadLen)
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;
206 if (pCmdMbox->bCmdInProgress)
208 TRACE0(pCmdMbox->hReport, REPORT_SEVERITY_ERROR, "cmdMbox_SendCommand(): Trying to send Cmd while other Cmd is still in progres!\n");
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);
219 /* Add the CMDMBOX_HEADER_LEN to the write length */
220 pCmdMbox->uWriteLen = uWriteLen + CMDMBOX_HEADER_LEN;
222 /* Must make sure that the length is multiple of 32 bit */
223 if (pCmdMbox->uWriteLen & 0x3)
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;
229 /* no other command can start the send process till bCmdInProgress will return to TI_FALSE*/
230 pCmdMbox->bCmdInProgress = TI_TRUE;
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);
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)
243 /* start the CmdMbox timer */
244 tmr_StartTimer (pCmdMbox->hCmdMboxTimer, cmdMbox_TimeOut, hCmdMbox, CMDMBOX_WAIT_TIMEOUT, TI_FALSE);
246 /* Send the FW trigger */
247 twIf_Transact(pCmdMbox->hTwIf, pRegTxn);
250 return TXN_STATUS_PENDING;
255 * \brief Read the command's result
257 * \param hCmdMbox - Handle to CmdMbox
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.
264 * \sa cmdMbox_SendCommand, cmdMbox_TransferComplete
266 ETxnStatus cmdMbox_CommandComplete (TI_HANDLE hCmdMbox)
268 TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
269 TTxnStruct *pCmdTxn = (TTxnStruct*)&pCmdMbox->aCmdTxn[1].tTxnStruct;
270 Command_t *pCmd = (Command_t*)&pCmdMbox->aCmdTxn[1].tCmdMbox;
273 /* stop the CmdMbox timer */
274 tmr_StopTimer(pCmdMbox->hCmdMboxTimer);
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);
283 /* In case of a sync read, call the CB directly */
284 if (rc == TXN_STATUS_COMPLETE)
286 cmdMbox_TransferComplete(hCmdMbox);
289 return TXN_STATUS_COMPLETE;
294 * \brief Calls the cmdQueue_ResultReceived.
296 * \param hCmdMbox - Handle to CmdMbox
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.
304 * \sa cmdMbox_SendCommand, cmdMbox_TransferComplete
306 TI_STATUS cmdMbox_TransferComplete(TI_HANDLE hCmdMbox)
308 TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
310 /* Other commands can be sent to the FW */
311 pCmdMbox->bCmdInProgress = TI_FALSE;
313 cmdQueue_ResultReceived(pCmdMbox->hCmdQueue);
320 * \brief Handle cmdMbox timeout.
322 * \param hCmdMbox - Handle to CmdMbox
326 * Call fErrorCb() to handle the error.
328 * \sa cmdMbox_SendCommand
330 static void cmdMbox_TimeOut (TI_HANDLE hCmdMbox, TI_BOOL bTwdInitOccured)
332 TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
333 Command_t *pCmd = (Command_t*)&pCmdMbox->aCmdTxn[0].tCmdMbox;
335 TRACE0(pCmdMbox->hReport, REPORT_SEVERITY_ERROR , "cmdMbox_TimeOut: Timeout occured in CmdMbox\n");
338 if (pCmdMbox->fErrorCb != NULL)
340 pCmdMbox->fErrorCb (pCmdMbox->hCmdQueue,
341 (TI_UINT32)pCmd->cmdID,
343 (void *)pCmd->parameters);
349 * \brief configure the mailbox address.
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
357 * Called from HwInit to read the command mailbox address.
361 TI_STATUS cmdMbox_ConfigHw (TI_HANDLE hCmdMbox, fnotify_t fCb, TI_HANDLE hCb)
363 TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
364 TTxnStruct *pRegTxn = (TTxnStruct*)&pCmdMbox->aRegTxn[1].tTxnStruct;
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)
376 pCmdMbox->uFwAddr = pCmdMbox->aRegTxn[1].uRegister;
384 * \brief Cb to cmdMbox_ConfigHw
386 * \param hCmdMbox - Handle to CmdMbox
393 static void cmdMbox_ConfigHwCb (TI_HANDLE hCmdMbox, TTxnStruct *pTxn)
395 TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
397 pCmdMbox->uFwAddr = pCmdMbox->aRegTxn[1].uRegister;
399 /* Call back the original State Machine */
400 pCmdMbox->fCb(pCmdMbox->hCb, TI_OK);
405 * \brief Restart the module upon driver stop or restart
407 * \param hCmdMbox - Handle to CmdMbox
414 TI_STATUS cmdMbox_Restart (TI_HANDLE hCmdMbox)
416 TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
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;
429 * \brief Return the latest command status
431 * \param hCmdMbox - Handle to CmdMbox
432 * \return TI_OK or TI_NOK
438 TI_STATUS cmdMbox_GetStatus (TI_HANDLE hCmdMbox, CommandStatus_e *cmdStatus)
440 TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
441 Command_t *pCmd = (Command_t*)&pCmdMbox->aCmdTxn[1].tCmdMbox;
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;
451 * \brief Return the MBox address
453 * \param hCmdMbox - Handle to CmdMbox
454 * \return MBox address
460 TI_UINT32 cmdMbox_GetMboxAddress (TI_HANDLE hCmdMbox)
462 TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
464 return pCmdMbox->uFwAddr;
469 * \brief Return the Command parameters buffer
471 * \param hCmdMbox - Handle to CmdMbox
472 * \param pParamBuf - Holds the returned buffer
476 * Copying the command's data to pParamBuf
480 void cmdMbox_GetCmdParams (TI_HANDLE hCmdMbox, TI_UINT8* pParamBuf)
482 TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
483 Command_t *pCmd = (Command_t*)&pCmdMbox->aCmdTxn[1].tCmdMbox;
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
490 os_memoryCopy (pCmdMbox->hOs,
492 (void *)pCmd->parameters,
493 pCmdMbox->uReadLen - CMDMBOX_HEADER_LEN);
500 void cmdMbox_PrintInfo(TI_HANDLE hCmdMbox)
503 TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
505 WLAN_OS_REPORT(("Print cmdMbox module info\n"));
506 WLAN_OS_REPORT(("=========================\n"));
507 WLAN_OS_REPORT(("bCmdInProgress = %d\n", pCmdMbox->bCmdInProgress));