OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / hardware / ti / wlan / wl1271 / TWD / FW_Transfer / CmdMBox.c
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