• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * CmdMBox.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  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  */
cmdMbox_Create(TI_HANDLE hOs)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  */
cmdMbox_Destroy(TI_HANDLE hCmdMbox)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  */
cmdMbox_Init(TI_HANDLE hCmdMbox,TI_HANDLE hReport,TI_HANDLE hTwIf,TI_HANDLE hTimer,TI_HANDLE hCmdQueue,TCmdMboxErrorCb fErrorCb)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     pCmdMbox->hCmdMboxTimer = hTimer;
157 
158     pCmdMbox->uFwAddr = 0;
159     pCmdMbox->uReadLen = 0;
160     pCmdMbox->uWriteLen = 0;
161     pCmdMbox->bCmdInProgress = TI_FALSE;
162     pCmdMbox->fErrorCb = fErrorCb;
163 
164 	/* allocate OS timer memory */
165     pCmdMbox->hCmdMboxTimer = tmr_CreateTimer (hTimer);
166 	if (pCmdMbox->hCmdMboxTimer == NULL)
167 	{
168         TRACE0(pCmdMbox->hReport, REPORT_SEVERITY_ERROR, "cmdMbox_Init(): Failed to create hCmdMboxTimer!\n");
169 		return TI_NOK;
170 	}
171 
172     return TI_OK;
173 }
174 
175 
176 /*
177  * \brief	Send the Command to the Mailbox
178  *
179  * \param  hCmdMbox  - Handle to CmdMbox
180  * \param  cmdType  -
181  * \param  pParamsBuf  - The buffer that will be written to the mailbox
182  * \param  uWriteLen  - Length of data to write to the mailbox
183  * \param  uReadLen  - Length of data to read from the mailbox (when the result is received)
184  * \return TI_PENDING
185  *
186  * \par Description
187  * Copy the buffer given to a local struct, update the write & read lengths
188  * and send to the FW's mailbox.
189  *
190  *       ------------------------------------------------------
191  *      | CmdMbox Header | Cmd Header    | Command parameters |
192  *      ------------------------------------------------------
193  *      | ID   | Status  | Type | Length | Command parameters |
194  *      ------------------------------------------------------
195  *       16bit   16bit    16bit   16bit
196  *
197  * \sa cmdMbox_CommandComplete
198  */
cmdMbox_SendCommand(TI_HANDLE hCmdMbox,Command_e cmdType,TI_UINT8 * pParamsBuf,TI_UINT32 uWriteLen,TI_UINT32 uReadLen)199 TI_STATUS cmdMbox_SendCommand       (TI_HANDLE hCmdMbox, Command_e cmdType, TI_UINT8* pParamsBuf, TI_UINT32 uWriteLen, TI_UINT32 uReadLen)
200 {
201     TCmdMbox   *pCmdMbox = (TCmdMbox *)hCmdMbox;
202     TTxnStruct *pCmdTxn = (TTxnStruct*)&pCmdMbox->aCmdTxn[0].tTxnStruct;
203     TTxnStruct *pRegTxn = (TTxnStruct*)&pCmdMbox->aRegTxn[0].tTxnStruct;
204     Command_t  *pCmd = (Command_t*)&pCmdMbox->aCmdTxn[0].tCmdMbox;
205 
206 
207     if (pCmdMbox->bCmdInProgress)
208     {
209         TRACE0(pCmdMbox->hReport, REPORT_SEVERITY_ERROR, "cmdMbox_SendCommand(): Trying to send Cmd while other Cmd is still in progres!\n");
210         return TI_NOK;
211     }
212 
213     /* Add the CMDMBOX_HEADER_LEN to the read length, used when reading the result later on */
214     pCmdMbox->uReadLen = uReadLen + CMDMBOX_HEADER_LEN;
215     /* Prepare the Cmd Hw template */
216     pCmd->cmdID = cmdType;
217     pCmd->cmdStatus = TI_OK;
218     os_memoryCopy (pCmdMbox->hOs, (void *)pCmd->parameters, (void *)pParamsBuf, uWriteLen);
219 
220     /* Add the CMDMBOX_HEADER_LEN to the write length */
221     pCmdMbox->uWriteLen = uWriteLen + CMDMBOX_HEADER_LEN;
222 
223     /* Must make sure that the length is multiple of 32 bit */
224     if (pCmdMbox->uWriteLen & 0x3)
225     {
226         TRACE1(pCmdMbox->hReport, REPORT_SEVERITY_WARNING, "cmdMbox_SendCommand(): Command length isn't 32bit aligned! CmdId=%d\n", pCmd->cmdID);
227         pCmdMbox->uWriteLen = (pCmdMbox->uWriteLen + 4) & 0xFFFFFFFC;
228     }
229 
230     /* no other command can start the send process  till bCmdInProgress will return to TI_FALSE*/
231     pCmdMbox->bCmdInProgress = TI_TRUE;
232 
233     /* Build the command TxnStruct */
234     TXN_PARAM_SET(pCmdTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR)
235     BUILD_TTxnStruct(pCmdTxn, pCmdMbox->uFwAddr, pCmd, pCmdMbox->uWriteLen, NULL, NULL)
236     /* Send the command */
237     twIf_Transact(pCmdMbox->hTwIf, pCmdTxn);
238 
239     /* Build the trig TxnStruct */
240     pCmdMbox->aRegTxn[0].uRegister = INTR_TRIG_CMD;
241     TXN_PARAM_SET(pRegTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR)
242     BUILD_TTxnStruct(pRegTxn, ACX_REG_INTERRUPT_TRIG, &(pCmdMbox->aRegTxn[0].uRegister), REGISTER_SIZE, NULL, NULL)
243 
244     /* start the CmdMbox timer */
245     tmr_StartTimer (pCmdMbox->hCmdMboxTimer, cmdMbox_TimeOut, hCmdMbox, CMDMBOX_WAIT_TIMEOUT, TI_FALSE);
246 
247     /* Send the FW trigger */
248     twIf_Transact(pCmdMbox->hTwIf, pRegTxn);
249 
250 
251     return TXN_STATUS_PENDING;
252 }
253 
254 
255 /*
256  * \brief	Read the command's result
257  *
258  * \param  hCmdMbox  - Handle to CmdMbox
259  * \return void
260  *
261  * \par Description
262  * This function is called from FwEvent module uppon receiving command complete interrupt.
263  * It issues a read transaction from the mailbox with a CB.
264  *
265  * \sa cmdMbox_SendCommand, cmdMbox_TransferComplete
266  */
cmdMbox_CommandComplete(TI_HANDLE hCmdMbox)267 void cmdMbox_CommandComplete (TI_HANDLE hCmdMbox)
268 {
269     TCmdMbox   *pCmdMbox = (TCmdMbox *)hCmdMbox;
270     TTxnStruct *pCmdTxn = (TTxnStruct*)&pCmdMbox->aCmdTxn[1].tTxnStruct;
271     Command_t  *pCmd = (Command_t*)&pCmdMbox->aCmdTxn[1].tCmdMbox;
272     ETxnStatus  rc;
273 
274     /* stop the CmdMbox timer */
275     tmr_StopTimer(pCmdMbox->hCmdMboxTimer);
276 
277     /* Build the command TxnStruct */
278     TXN_PARAM_SET(pCmdTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_READ, TXN_INC_ADDR)
279     /* Applying a CB in case of an async read */
280     BUILD_TTxnStruct(pCmdTxn, pCmdMbox->uFwAddr, pCmd, pCmdMbox->uReadLen,(TTxnDoneCb)cmdMbox_TransferComplete, hCmdMbox)
281     /* Send the command */
282     rc = twIf_Transact(pCmdMbox->hTwIf, pCmdTxn);
283 
284     /* In case of a sync read, call the CB directly */
285     if (rc == TXN_STATUS_COMPLETE)
286     {
287         cmdMbox_TransferComplete(hCmdMbox);
288     }
289 }
290 
291 
292 /*
293  * \brief	Calls the cmdQueue_ResultReceived.
294  *
295  * \param  hCmdMbox  - Handle to CmdMbox
296  * \return TI_OK
297  *
298  * \par Description
299  * This function is called from cmdMbox_CommandComplete on a sync read, or from TwIf as a CB on an async read.
300  * It calls cmdQueue_ResultReceived to continue the result handling procces & switch the bCmdInProgress flag to TI_FALSE,
301  * meaning other commands can be sent to the FW.
302  *
303  * \sa cmdMbox_SendCommand, cmdMbox_TransferComplete
304  */
cmdMbox_TransferComplete(TI_HANDLE hCmdMbox)305 TI_STATUS cmdMbox_TransferComplete(TI_HANDLE hCmdMbox)
306 {
307     TCmdMbox   *pCmdMbox = (TCmdMbox *)hCmdMbox;
308 
309     /* Other commands can be sent to the FW */
310     pCmdMbox->bCmdInProgress = TI_FALSE;
311 
312     cmdQueue_ResultReceived(pCmdMbox->hCmdQueue);
313 
314     return TI_OK;
315 }
316 
317 
318 /*
319  * \brief	Handle cmdMbox timeout.
320  *
321  * \param  hCmdMbox  - Handle to CmdMbox
322  * \return TI_OK
323  *
324  * \par Description
325  * Call fErrorCb() to handle the error.
326  *
327  * \sa cmdMbox_SendCommand
328  */
cmdMbox_TimeOut(TI_HANDLE hCmdMbox,TI_BOOL bTwdInitOccured)329 static void cmdMbox_TimeOut (TI_HANDLE hCmdMbox, TI_BOOL bTwdInitOccured)
330 {
331     TCmdMbox   *pCmdMbox = (TCmdMbox *)hCmdMbox;
332     Command_t  *pCmd = (Command_t*)&pCmdMbox->aCmdTxn[0].tCmdMbox;
333 
334     TRACE0(pCmdMbox->hReport, REPORT_SEVERITY_ERROR , "cmdMbox_TimeOut: Timeout occured in CmdMbox\n");
335 
336     /* Call error CB */
337     if (pCmdMbox->fErrorCb != NULL)
338     {
339         pCmdMbox->fErrorCb (pCmdMbox->hCmdQueue,
340                             (TI_UINT32)pCmd->cmdID,
341                             CMD_STATUS_TIMEOUT,
342                             (void *)pCmd->parameters);
343     }
344 }
345 
346 
347 /*
348  * \brief	configure the mailbox address.
349  *
350  * \param  hCmdMbox  - Handle to CmdMbox
351  * \param  fCb  - Pointer to the CB
352  * \param  hCb  - Cb's handle
353  * \return TI_OK or TI_PENDING
354  *
355  * \par Description
356  * Called from HwInit to read the command mailbox address.
357  *
358  * \sa
359  */
cmdMbox_ConfigHw(TI_HANDLE hCmdMbox,fnotify_t fCb,TI_HANDLE hCb)360 TI_STATUS cmdMbox_ConfigHw (TI_HANDLE hCmdMbox, fnotify_t fCb, TI_HANDLE hCb)
361 {
362     TCmdMbox   *pCmdMbox = (TCmdMbox *)hCmdMbox;
363     TTxnStruct *pRegTxn = (TTxnStruct*)&pCmdMbox->aRegTxn[1].tTxnStruct;
364     TI_STATUS   rc;
365 
366     pCmdMbox->fCb = fCb;
367     pCmdMbox->hCb = hCb;
368     /* Build the command TxnStruct */
369     TXN_PARAM_SET(pRegTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_READ, TXN_INC_ADDR)
370     BUILD_TTxnStruct(pRegTxn, REG_COMMAND_MAILBOX_PTR, &(pCmdMbox->aRegTxn[1].uRegister), REGISTER_SIZE,(TTxnDoneCb)cmdMbox_ConfigHwCb, hCmdMbox)
371     /* Get the command mailbox address */
372     rc = twIf_Transact(pCmdMbox->hTwIf, pRegTxn);
373     if (rc == TXN_STATUS_COMPLETE)
374     {
375         pCmdMbox->uFwAddr = pCmdMbox->aRegTxn[1].uRegister;
376     }
377 
378     return rc;
379 }
380 
381 
382 /*
383  * \brief	Cb to cmdMbox_ConfigHw
384  *
385  * \param  hCmdMbox  - Handle to CmdMbox
386  * \return TI_OK
387  *
388  * \par Description
389  *
390  * \sa
391  */
cmdMbox_ConfigHwCb(TI_HANDLE hCmdMbox,TTxnStruct * pTxn)392 static void cmdMbox_ConfigHwCb (TI_HANDLE hCmdMbox, TTxnStruct *pTxn)
393 {
394     TCmdMbox   *pCmdMbox = (TCmdMbox *)hCmdMbox;
395 
396     pCmdMbox->uFwAddr = pCmdMbox->aRegTxn[1].uRegister;
397 
398     /* Call back the original State Machine */
399     pCmdMbox->fCb(pCmdMbox->hCb, TI_OK);
400 }
401 
402 
403 /*
404  * \brief	Restart the module upon driver stop or restart
405  *
406  * \param  hCmdMbox  - Handle to CmdMbox
407  * \return TI_OK
408  *
409  * \par Description
410  *
411  * \sa
412  */
cmdMbox_Restart(TI_HANDLE hCmdMbox)413 TI_STATUS cmdMbox_Restart (TI_HANDLE hCmdMbox)
414 {
415     TCmdMbox   *pCmdMbox = (TCmdMbox *)hCmdMbox;
416 
417     /* Stop the timeout timer if running and reset the state */
418     tmr_StopTimer (pCmdMbox->hCmdMboxTimer);
419     pCmdMbox->bCmdInProgress = TI_FALSE;
420     pCmdMbox->uReadLen       = 0;
421     pCmdMbox->uWriteLen      = 0;
422 
423     return TI_OK;
424 }
425 
426 
427 /*
428  * \brief	Return the latest command status
429  *
430  * \param  hCmdMbox  - Handle to CmdMbox
431  * \return TI_OK or TI_NOK
432  *
433  * \par Description
434  *
435  * \sa
436  */
cmdMbox_GetStatus(TI_HANDLE hCmdMbox,CommandStatus_e * cmdStatus)437 TI_STATUS cmdMbox_GetStatus (TI_HANDLE hCmdMbox, CommandStatus_e *cmdStatus)
438 {
439     TCmdMbox   *pCmdMbox = (TCmdMbox *)hCmdMbox;
440     Command_t  *pCmd = (Command_t*)&pCmdMbox->aCmdTxn[1].tCmdMbox;
441     TI_STATUS   status;
442 
443     status = (pCmd->cmdStatus == CMD_STATUS_SUCCESS) ? TI_OK : TI_NOK;
444     TRACE2(pCmdMbox->hReport, REPORT_SEVERITY_INFORMATION , "cmdMbox_GetStatus: TI_STATUS = (%d) <= pCmdMbox->tCmdMbox.cmdStatus = %d\n", status, pCmd->cmdStatus);
445     *cmdStatus = pCmd->cmdStatus;
446     return status;
447 }
448 
449 /*
450  * \brief	Return the MBox address
451  *
452  * \param  hCmdMbox  - Handle to CmdMbox
453  * \return MBox address
454  *
455  * \par Description
456  *
457  * \sa
458  */
cmdMbox_GetMboxAddress(TI_HANDLE hCmdMbox)459 TI_UINT32 cmdMbox_GetMboxAddress (TI_HANDLE hCmdMbox)
460 {
461     TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
462 
463     return pCmdMbox->uFwAddr;
464 }
465 
466 
467 /*
468  * \brief	Return the Command parameters buffer
469  *
470  * \param  hCmdMbox  - Handle to CmdMbox
471  * \param  pParamBuf  - Holds the returned buffer
472  * \return
473  *
474  * \par Description
475  * Copying the command's data to pParamBuf
476  *
477  * \sa
478  */
cmdMbox_GetCmdParams(TI_HANDLE hCmdMbox,TI_UINT8 * pParamBuf)479 void cmdMbox_GetCmdParams (TI_HANDLE hCmdMbox, TI_UINT8* pParamBuf)
480 {
481     TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
482     Command_t  *pCmd = (Command_t*)&pCmdMbox->aCmdTxn[1].tCmdMbox;
483 
484     /*
485      * Copy the results to the caller buffer:
486      * We need to copy only the data without the cmdMbox header,
487      * otherwise we will overflow the pParambuf
488      */
489     os_memoryCopy (pCmdMbox->hOs,
490                    (void *)pParamBuf,
491                    (void *)pCmd->parameters,
492                    pCmdMbox->uReadLen - CMDMBOX_HEADER_LEN);
493 
494 }
495 
496 
497 #ifdef TI_DBG
498 
cmdMbox_PrintInfo(TI_HANDLE hCmdMbox)499 void cmdMbox_PrintInfo(TI_HANDLE hCmdMbox)
500 {
501 #ifdef REPORT_LOG
502     TCmdMbox *pCmdMbox = (TCmdMbox *)hCmdMbox;
503 
504     WLAN_OS_REPORT(("Print cmdMbox module info\n"));
505     WLAN_OS_REPORT(("=========================\n"));
506     WLAN_OS_REPORT(("bCmdInProgress = %d\n", pCmdMbox->bCmdInProgress));
507 #endif
508 }
509 
510 #endif  /* TI_DBG */
511 
512 
513