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 */
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
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 */
cmdMbox_SendCommand(TI_HANDLE hCmdMbox,Command_e cmdType,TI_UINT8 * pParamsBuf,TI_UINT32 uWriteLen,TI_UINT32 uReadLen)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 */
cmdMbox_CommandComplete(TI_HANDLE hCmdMbox)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 */
cmdMbox_TransferComplete(TI_HANDLE hCmdMbox)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 */
cmdMbox_TimeOut(TI_HANDLE hCmdMbox,TI_BOOL bTwdInitOccured)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 */
cmdMbox_ConfigHw(TI_HANDLE hCmdMbox,fnotify_t fCb,TI_HANDLE hCb)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 */
cmdMbox_ConfigHwCb(TI_HANDLE hCmdMbox,TTxnStruct * pTxn)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 */
cmdMbox_Restart(TI_HANDLE hCmdMbox)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 */
cmdMbox_GetStatus(TI_HANDLE hCmdMbox,CommandStatus_e * cmdStatus)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 */
cmdMbox_GetMboxAddress(TI_HANDLE hCmdMbox)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 */
cmdMbox_GetCmdParams(TI_HANDLE hCmdMbox,TI_UINT8 * pParamBuf)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
cmdMbox_PrintInfo(TI_HANDLE hCmdMbox)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