8e95423995db05292b165d9eb7c6311b42f3af8a
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / procMgr / hlos / knl / Processor.c
1 /*
2  *  @file   Processor.c
3  *
4  *  @brief      Generic Processor that calls into specific Processor instance
5  *              through function table interface.
6  *
7  *
8  *  ============================================================================
9  *
10  *  Copyright (c) 2008-2015, Texas Instruments Incorporated
11  *
12  *  Redistribution and use in source and binary forms, with or without
13  *  modification, are permitted provided that the following conditions
14  *  are met:
15  *
16  *  *  Redistributions of source code must retain the above copyright
17  *     notice, this list of conditions and the following disclaimer.
18  *
19  *  *  Redistributions in binary form must reproduce the above copyright
20  *     notice, this list of conditions and the following disclaimer in the
21  *     documentation and/or other materials provided with the distribution.
22  *
23  *  *  Neither the name of Texas Instruments Incorporated nor the names of
24  *     its contributors may be used to endorse or promote products derived
25  *     from this software without specific prior written permission.
26  *
27  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
29  *  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
31  *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32  *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33  *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
34  *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
35  *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
36  *  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
37  *  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38  *  Contact information for paper mail:
39  *  Texas Instruments
40  *  Post Office Box 655303
41  *  Dallas, Texas 75265
42  *  Contact information:
43  *  http://www-k.ext.ti.com/sc/technical-support/product-information-centers.htm?
44  *  DCMP=TIHomeTracking&HQS=Other+OT+home_d_contact
45  *  ============================================================================
46  *
47  */
52 /*-------------------------   Standard headers   -----------------------------*/
53 #include <ti/syslink/Std.h>
55 /*-------------------------   OSAL and utils   -------------------------------*/
56 #include <ti/syslink/utils/Trace.h>
57 #include <ti/syslink/utils/List.h>
58 #include <OsalMutex.h>
60 /* Module level headers */
61 #include <ProcDefs.h>
62 #include <Processor.h>
64 /*QNX specific header include */
65 #include <sys/neutrino.h>
66 #include <errno.h>
67 #include <pthread.h>
69 #if defined (__cplusplus)
70 extern "C" {
71 #endif
74 /* =============================================================================
75  * Functions called by ProcMgr
76  * =============================================================================
77  */
78 /*!
79  *  @brief      Function to attach to the Processor.
80  *
81  *              This function calls into the specific Processor implementation
82  *              to attach to it.
83  *              This function is called from the ProcMgr attach function, and
84  *              hence is used to perform any activities that may be required
85  *              once the slave is powered up.
86  *              Depending on the type of Processor, this function may or may not
87  *              perform any activities.
88  *
89  *  @param      handle     Handle to the Processor object
90  *  @param      params     Attach parameters
91  *
92  *  @sa         Processor_detach
93  */
94 inline
95 Int
96 Processor_attach (Processor_Handle handle, Processor_AttachParams * params)
97 {
98     Int                status     = PROCESSOR_SUCCESS;
99     Processor_Object * procHandle = (Processor_Object *) handle;
101     GT_2trace (curTrace, GT_ENTER, "Processor_attach", handle, params);
103     GT_assert (curTrace, (handle != NULL));
104     GT_assert (curTrace, (params != NULL));
106     /* No parameter validation here since this is an internal module, and
107      * validation has already happened at the ProcMgr level.
108      */
109     GT_assert (curTrace, (procHandle->procFxnTable.attach != NULL));
111     procHandle->bootMode = params->params->bootMode;
112     status = procHandle->procFxnTable.attach (handle, params);
113 #if !defined(IPC_BUILD_OPTIMIZE)
114     if (status < 0) {
115         GT_setFailureReason (curTrace,
116                              GT_4CLASS,
117                              "Processor_attach",
118                              status,
119                              "Failed to attach to the specific Processor!");
120     }
121     else {
122 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
123         if (procHandle->bootMode == ProcMgr_BootMode_Boot) {
124             Processor_setState(handle, ProcMgr_State_Powered);
125         }
126         else if ((procHandle->bootMode == ProcMgr_BootMode_NoLoad_Pwr) ||
127                  (procHandle->bootMode == ProcMgr_BootMode_NoLoad_NoPwr)) {
128             Processor_setState(handle, ProcMgr_State_Loaded);
129         }
130         else if (procHandle->bootMode == ProcMgr_BootMode_NoBoot) {
131             Processor_setState(handle, ProcMgr_State_Running);
132             /* TBD: Check actual state from h/w. */
133         }
134 #if !defined(IPC_BUILD_OPTIMIZE)
135     }
136 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
138     GT_1trace (curTrace, GT_LEAVE, "Processor_attach", status);
140     /*! @retval PROCESSOR_SUCCESS Operation successful */
141     return status;
145 /*!
146  *  @brief      Function to detach from the Processor.
147  *
148  *              This function calls into the specific Processor implementation
149  *              to detach from it.
150  *              This function is called from the ProcMgr detach function, and
151  *              hence is useful to perform any activities that may be required
152  *              before the slave is powered down.
153  *              Depending on the type of Processor, this function may or may not
154  *              perform any activities.
155  *
156  *  @param      handle     Handle to the Processor object
157  *
158  *  @sa         Processor_attach
159  */
160 inline
161 Int
162 Processor_detach (Processor_Handle handle)
164     Int                status     = PROCESSOR_SUCCESS;
165     Processor_Object * procHandle = (Processor_Object *) handle;
167     GT_1trace (curTrace, GT_ENTER, "Processor_detach", handle);
169     GT_assert (curTrace, (handle != NULL));
171     /* No parameter validation here since this is an internal module, and
172      * validation has already happened at the ProcMgr level.
173      */
174     GT_assert (curTrace, (procHandle->procFxnTable.detach != NULL));
175     status = procHandle->procFxnTable.detach (handle);
176 #if !defined(IPC_BUILD_OPTIMIZE)
177     if (status < 0) {
178         GT_setFailureReason (curTrace,
179                              GT_4CLASS,
180                              "Processor_detach",
181                              status,
182                              "Failed to detach from the specific Processor!");
183     }
184     else {
185 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
186         /* For all boot modes, at the end of detach, the Processor is in
187          * unknown state.
188          */
189         Processor_setState(handle, ProcMgr_State_Unknown);
190 #if !defined(IPC_BUILD_OPTIMIZE)
191     }
192 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
194     GT_1trace (curTrace, GT_LEAVE, "Processor_detach", status);
196     /*! @retval PROCESSOR_SUCCESS Operation successful */
197     return status;
201 /*!
202  *  @brief      Function to start the processor.
203  *
204  *              This function calls into the specific Processor implementation
205  *              to start the slave processor running.
206  *              This function starts the slave processor running, in most
207  *              devices, by programming its entry point into the boot location
208  *              of the slave processor and releasing it from reset.
209  *              The handle specifies the specific Processor instance to be used.
210  *
211  *  @param      handle     Handle to the Processor object
212  *  @param      entryPt    Entry point of the file loaded on the slave Processor
213  *
214  *  @sa         Processor_stop
215  */
216 inline
217 Int
218 Processor_start (Processor_Handle        handle,
219                  UInt32                  entryPt,
220                  Processor_StartParams * params)
222     Int                status     = PROCESSOR_SUCCESS;
223     Processor_Object * procHandle = (Processor_Object *) handle;
225     GT_3trace (curTrace, GT_ENTER, "Processor_start", handle, entryPt, params);
227     GT_assert (curTrace, (handle != NULL));
228     /* entryPt may be 0 for some devices. Cannot check for valid/invalid. */
229     GT_assert (curTrace, (params != NULL));
231     /* No parameter validation here since this is an internal module, and
232      * validation has already happened at the ProcMgr level.
233      */
234     GT_assert (curTrace, (procHandle->procFxnTable.start != NULL));
235     status = procHandle->procFxnTable.start (handle, entryPt, params);
236 #if !defined(IPC_BUILD_OPTIMIZE)
237     if (status < 0) {
238         GT_setFailureReason (curTrace,
239                              GT_4CLASS,
240                              "Processor_start",
241                              status,
242                              "Failed to start the slave processor!");
243     }
244     else {
245 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
246         if (    (procHandle->bootMode == ProcMgr_BootMode_Boot)
247             ||  (procHandle->bootMode == ProcMgr_BootMode_NoLoad_Pwr)
248             ||  (procHandle->bootMode == ProcMgr_BootMode_NoLoad_NoPwr)) {
249             Processor_setState(handle, ProcMgr_State_Running);
250         }
251 #if !defined(IPC_BUILD_OPTIMIZE)
252     }
253 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
255     GT_1trace (curTrace, GT_LEAVE, "Processor_start", status);
257     /*! @retval PROCESSOR_SUCCESS Operation successful */
258     return status;
262 /*!
263  *  @brief      Function to stop the processor.
264  *
265  *              This function calls into the specific Processor implementation
266  *              to stop the slave processor.
267  *              This function stops the slave processor running, in most
268  *              devices, by placing it in reset.
269  *              The handle specifies the specific Processor instance to be used.
270  *
271  *  @param      handle     Handle to the Processor object
272  *
273  *  @sa         Processor_start
274  */
275 inline
276 Int
277 Processor_stop (Processor_Handle handle)
279     Int                status     = PROCESSOR_SUCCESS;
280     Processor_Object * procHandle = (Processor_Object *) handle;
282     GT_1trace (curTrace, GT_ENTER, "Processor_stop", handle);
284     GT_assert (curTrace, (handle != NULL));
286     /* No parameter validation here since this is an internal module, and
287      * validation has already happened at the ProcMgr level.
288      */
289     GT_assert (curTrace, (procHandle->procFxnTable.stop != NULL));
290     if (Processor_getState(handle) == ProcMgr_State_Running ||
291         Processor_getState(handle) == ProcMgr_State_Mmu_Fault ||
292         Processor_getState(handle) == ProcMgr_State_Watchdog ||
293         Processor_getState(handle) == ProcMgr_State_Error) {
294         status = procHandle->procFxnTable.stop (handle);
295     }
296     else if (Processor_getState(handle) != ProcMgr_State_Suspended) {
297         status = PROCESSOR_E_INVALIDSTATE;
298     }
299 #if !defined(IPC_BUILD_OPTIMIZE)
300     if (status < 0) {
301         GT_setFailureReason (curTrace,
302                              GT_4CLASS,
303                              "Processor_stop",
304                              status,
305                              "Failed to stop the slave processor!");
306     }
307     else {
308 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
309         if (    (procHandle->bootMode == ProcMgr_BootMode_Boot)
310             ||  (procHandle->bootMode == ProcMgr_BootMode_NoLoad_Pwr)
311             ||  (procHandle->bootMode == ProcMgr_BootMode_NoLoad_NoPwr)) {
312             Processor_setState(handle, ProcMgr_State_Reset);
313         }
314 #if !defined(IPC_BUILD_OPTIMIZE)
315     }
316 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
318     GT_1trace (curTrace, GT_LEAVE, "Processor_stop", status);
320     /*! @retval PROCESSOR_SUCCESS Operation successful */
321     return status;
325 /*!
326  *  @brief      Function to read from the slave processor's memory.
327  *
328  *              This function calls into the specific Processor implementation
329  *              to read from the slave processor's memory. It reads from the
330  *              specified address in the processor's address space and copies
331  *              the required number of bytes into the specified buffer.
332  *              It returns the number of bytes actually read in the numBytes
333  *              parameter.
334  *              Depending on the processor implementation, it may result in
335  *              reading from shared memory or across a peripheral physical
336  *              connectivity.
337  *              The handle specifies the specific Processor instance to be used.
338  *
339  *  @param      handle     Handle to the Processor object
340  *  @param      procAddr   Address in host processor's address space of the
341  *                         memory region to read from.
342  *  @param      numBytes   IN/OUT parameter. As an IN-parameter, it takes in the
343  *                         number of bytes to be read. When the function
344  *                         returns, this parameter contains the number of bytes
345  *                         actually read.
346  *  @param      buffer     User-provided buffer in which the slave processor's
347  *                         memory contents are to be copied.
348  *
349  *  @sa         Processor_write
350  */
351 inline
352 Int
353 Processor_read (Processor_Handle handle,
354                 UInt32           procAddr,
355                 UInt32 *         numBytes,
356                 Ptr              buffer)
358     Int                status     = PROCESSOR_SUCCESS;
359     Processor_Object * procHandle = (Processor_Object *) handle;
361     GT_4trace (curTrace, GT_ENTER, "Processor_read",
362                handle, procAddr, numBytes, buffer);
364     GT_assert (curTrace, (handle   != NULL));
365     GT_assert (curTrace, (numBytes != NULL));
366     GT_assert (curTrace, (buffer   != NULL));
368     /* No parameter validation here since this is an internal module, and
369      * validation has already happened at the ProcMgr level.
370      */
371     GT_assert (curTrace, (procHandle->procFxnTable.read != NULL));
372     status = procHandle->procFxnTable.read (handle, procAddr, numBytes, buffer);
373 #if !defined(IPC_BUILD_OPTIMIZE)
374     if (status < 0) {
375         GT_setFailureReason (curTrace,
376                              GT_4CLASS,
377                              "Processor_read",
378                              status,
379                              "Failed to read from the slave processor!");
380     }
381 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
383     GT_1trace (curTrace, GT_LEAVE, "Processor_read", status);
385     /*! @retval PROCESSOR_SUCCESS Operation successful */
386     return status;
390 /*!
391  *  @brief      Function to write into the slave processor's memory.
392  *
393  *              This function calls into the specific Processor implementation
394  *              to write into the slave processor's memory. It writes into the
395  *              specified address in the processor's address space and copies
396  *              the required number of bytes from the specified buffer.
397  *              It returns the number of bytes actually written in the numBytes
398  *              parameter.
399  *              Depending on the processor implementation, it may result in
400  *              writing into shared memory or across a peripheral physical
401  *              connectivity.
402  *              The handle specifies the specific Processor instance to be used.
403  *
404  *  @param      handle     Handle to the Processor object
405  *  @param      procAddr   Address in host processor's address space of the
406  *                         memory region to write into.
407  *  @param      numBytes   IN/OUT parameter. As an IN-parameter, it takes in the
408  *                         number of bytes to be written. When the function
409  *                         returns, this parameter contains the number of bytes
410  *                         actually written.
411  *  @param      buffer     User-provided buffer from which the data is to be
412  *                         written into the slave processor's memory.
413  *
414  *  @sa         Processor_read
415  */
416 inline
417 Int
418 Processor_write (Processor_Handle handle,
419                  UInt32           procAddr,
420                  UInt32 *         numBytes,
421                  Ptr              buffer)
423     Int                status     = PROCESSOR_SUCCESS;
424     Processor_Object * procHandle = (Processor_Object *) handle;
426     GT_4trace (curTrace, GT_ENTER, "Processor_write",
427                handle, procAddr, numBytes, buffer);
429     GT_assert (curTrace, (handle   != NULL));
430     GT_assert (curTrace, (numBytes != NULL));
431     GT_assert (curTrace, (buffer   != NULL));
433     /* No parameter validation here since this is an internal module, and
434      * validation has already happened at the ProcMgr level.
435      */
436     GT_assert (curTrace, (procHandle->procFxnTable.write != NULL));
437     status = procHandle->procFxnTable.write (handle,
438                                              procAddr,
439                                              numBytes,
440                                              buffer);
441 #if !defined(IPC_BUILD_OPTIMIZE)
442     if (status < 0) {
443         GT_setFailureReason (curTrace,
444                              GT_4CLASS,
445                              "Processor_write",
446                              status,
447                              "Failed to write into the slave processor!");
448     }
449 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
451     GT_1trace (curTrace, GT_LEAVE, "Processor_write", status);
453     /*! @retval PROCESSOR_SUCCESS Operation successful */
454     return status;
458 /*!
459  *  @brief      Function to get the current state of the slave Processor.
460  *
461  *              This function gets the state of the slave processor as
462  *              maintained on the master Processor state machine. It does not
463  *              go to the slave processor to get its actual state at the time
464  *              when this API is called.
465  *
466  *  @param      handle   Handle to the Processor object
467  *
468  *  @sa         Processor_setState
469  */
470 ProcMgr_State
471 Processor_getState (Processor_Handle handle)
473     Processor_Object * procHandle = (Processor_Object *) handle;
475     GT_1trace (curTrace, GT_ENTER, "Processor_getState", handle);
477     GT_assert (curTrace, (handle != NULL));
479     /* No parameter validation here since this is an internal module, and
480      * validation has already happened at the ProcMgr level.
481      */
483     GT_1trace (curTrace, GT_LEAVE, "Processor_getState", procHandle->state);
485     /*! @retval Processor state */
486     return procHandle->state;
490 /*!
491  *  @brief      Function to set the current state of the slave Processor
492  *              to specified value.
493  *
494  *              This function is used to set the state of the processor to the
495  *              value as specified. This function may be used by external
496  *              entities that affect the state of the slave processor, such as
497  *              PwrMgr, error handler, or ProcMgr.
498  *
499  *  @param      handle   Handle to the Processor object
500  *  @param      state    State that needs to be set for the Processor object
501  *
502  *  @sa         Processor_getState
503  */
504 Void
505 Processor_notify (Processor_Handle handle, ProcMgr_State oldState, ProcMgr_State state)
507     Processor_Object * procHandle = (Processor_Object *) handle;
508     List_Elem * elem = NULL;
509     Processor_RegisterElem * regElem = NULL;
510     IArg key = NULL;
511     Int i = 0;
513     GT_1trace (curTrace, GT_ENTER, "Processor_notify", handle);
515     GT_assert (curTrace, (handle != NULL));
517     GT_1trace (curTrace,
518                GT_3CLASS,
519                "Processor_notify: New state: %d",
520                state);
522     key = OsalMutex_enter(procHandle->notifiersLock);
523     while((elem = List_next(procHandle->registeredNotifiers, elem)) != NULL) {
524         regElem = (Processor_RegisterElem *)elem;
525         for (i = 0; regElem->info->state[i] != ProcMgr_State_EndValue; i++) {
526             if (state == regElem->info->state[i])
527                 break;
528         }
529         if (regElem->info->state[i] == ProcMgr_State_EndValue) {
530             continue;
531         }
533         /* If timeout is non-NULL, cancel the timer */
534         if (regElem->timer != -1) {
535             struct itimerspec value ;
536             value.it_value.tv_sec = 0;
537             value.it_value.tv_nsec = 0;
538             value.it_interval.tv_sec = 0;
539             value.it_interval.tv_nsec = 0;
540             timer_settime(regElem->timer, 0, &value, NULL);
542             timer_delete(regElem->timer);
543             regElem->timer = -1;
544         }
546         regElem->info->cbFxn(procHandle->procId,
547                              NULL,
548                              oldState,
549                              state,
550                              ProcMgr_EventStatus_Event,
551                              regElem->info->arg);
552     }
553     OsalMutex_leave(procHandle->notifiersLock, key);
555     GT_0trace (curTrace, GT_LEAVE, "Processor_notify");
559 /*!
560  *  @brief      Function to set the current state of the slave Processor
561  *              to specified value.
562  *
563  *              This function is used to set the state of the processor to the
564  *              value as specified. This function may be used by external
565  *              entities that affect the state of the slave processor, such as
566  *              PwrMgr, error handler, or ProcMgr.
567  *
568  *  @param      handle   Handle to the Processor object
569  *  @param      state    State that needs to be set for the Processor object
570  *
571  *  @sa         Processor_getState
572  */
573 Void
574 Processor_setState (Processor_Handle handle, ProcMgr_State state)
576     Processor_Object * procHandle = (Processor_Object *) handle;
577     ProcMgr_State oldState;
579     GT_1trace (curTrace, GT_ENTER, "Processor_setState", handle);
581     GT_assert (curTrace, (handle != NULL));
583     GT_2trace (curTrace,
584                GT_3CLASS,
585                "Processor_setState: Old state: %d, New state: %d",
586                procHandle->state,
587                state);
589     oldState = procHandle->state;
590     procHandle->state = state;
592     /* No parameter validation here since this is an internal module, and
593      * validation has already happened at the ProcMgr level.
594      */
595     if (oldState != state)
596         Processor_notify(handle, oldState, state);
598     GT_0trace (curTrace, GT_LEAVE, "Processor_setState");
602 /*!
603  *  @brief      Function to perform device-dependent operations.
604  *
605  *              This function calls into the specific Processor implementation
606  *              to perform device dependent control operations. The control
607  *              operations supported by the device are exposed directly by the
608  *              specific implementation of the Processor interface. These
609  *              commands and their specific argument types are used with this
610  *              function.
611  *
612  *  @param      handle     Handle to the Processor object
613  *  @param      cmd        Device specific processor command
614  *  @param      arg        Arguments specific to the type of command.
615  *
616  *  @sa
617  */
618 inline
619 Int
620 Processor_control (Processor_Handle handle, Int32 cmd, Ptr arg)
622     Int                status     = PROCESSOR_SUCCESS;
623     Processor_Object * procHandle = (Processor_Object *) handle;
625     GT_3trace (curTrace, GT_ENTER, "Processor_control", handle, cmd, arg);
627     GT_assert (curTrace, (handle   != NULL));
628     /* cmd and arg can be 0/NULL, so cannot check for validity. */
630     /* No parameter validation here since this is an internal module, and
631      * validation has already happened at the ProcMgr level.
632      */
633     GT_assert (curTrace, (procHandle->procFxnTable.control != NULL));
634     status = procHandle->procFxnTable.control (handle, cmd, arg);
635 #if !defined(IPC_BUILD_OPTIMIZE)
636     if (status < 0) {
637         GT_setFailureReason (curTrace,
638                              GT_4CLASS,
639                              "Processor_control",
640                              status,
641                              "Processor control command failed!");
642     }
643 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
645     GT_1trace (curTrace, GT_LEAVE, "Processor_control", status);
647     /*! @retval PROCESSOR_SUCCESS Operation successful */
648     return status;
652 /*!
653  *  @brief      Function to translate slave physical address to master physical
654  *              address.
655  *
656  *  @param      handle     Handle to the Processor object
657  *  @param      dstAddr    Returned: master physical address.
658  *  @param      srcAddr    Slave physical address.
659  *
660  *  @sa
661  */
662 inline
663 Int
664 Processor_translateAddr (Processor_Handle handle,
665                          UInt32 *         dstAddr,
666                          UInt32           srcAddr)
668     Int                status     = PROCESSOR_SUCCESS;
669     Processor_Object * procHandle = (Processor_Object *) handle;
671     GT_3trace (curTrace, GT_ENTER, "Processor_translateAddr",
672                handle, dstAddr, srcAddr);
674     GT_assert (curTrace, (handle        != NULL));
675     GT_assert (curTrace, (dstAddr       != NULL));
677     /* No parameter validation here since this is an internal module, and
678      * validation has already happened at the ProcMgr level.
679      */
680     GT_assert (curTrace, (procHandle->procFxnTable.translateAddr != NULL));
681     status = procHandle->procFxnTable.translateAddr (handle,
682                                                      dstAddr,
683                                                      srcAddr);
684 #if !defined(IPC_BUILD_OPTIMIZE)
685     if (status < 0) {
686         GT_setFailureReason (curTrace,
687                              GT_4CLASS,
688                              "Processor_translateAddr",
689                              status,
690                              "Processor address translation failed!");
691     }
692 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
694     GT_1trace (curTrace, GT_LEAVE, "Processor_translateAddr", status);
696     /*! @retval PROCESSOR_SUCCESS Operation successful */
697     return status;
700 /*!
701  *  @brief      Function to translate slave virtual address to master physical
702  *              address using MMU page table entries
703  *
704  *  @param      handle     Handle to the Processor object
705  *  @param      dstAddr    Returned: master physical address.
706  *  @param      srcAddr    Slave virtual address.
707  *
708  *  @sa
709  */
710 inline
711 Int
712 Processor_translateFromPte(Processor_Handle handle,
713                          UInt32 *         dstAddr,
714                          UInt32           srcAddr)
716     Int                status     = PROCESSOR_SUCCESS;
717     Processor_Object * procHandle = (Processor_Object *) handle;
719     GT_3trace (curTrace, GT_ENTER, "Processor_translateFromPte",
720                handle, dstAddr, srcAddr);
722     GT_assert (curTrace, (handle        != NULL));
723     GT_assert (curTrace, (dstAddr       != NULL));
725     /* No parameter validation here since this is an internal module, and
726      * validation has already happened at the ProcMgr level.
727      */
728     if (procHandle->procFxnTable.translateFromPte != NULL) {
729         status = procHandle->procFxnTable.translateFromPte(
730             handle, dstAddr, srcAddr);
731     }
732     else {
733         status = PROCESSOR_E_NOTSUPPORTED;
734     }
736 #if !defined(IPC_BUILD_OPTIMIZE)
737     if (status < 0) {
738         GT_setFailureReason (curTrace,
739                              GT_4CLASS,
740                              "Processor_translateFromPte",
741                              status,
742                              "Processor address translation failed!");
743     }
744 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
746     GT_1trace (curTrace, GT_LEAVE, "Processor_translateFromPte", status);
748     /*! @retval PROCESSOR_SUCCESS Operation successful */
749     return status;
752 /*!
753  *  @brief      Function to map address to slave address space.
754  *
755  *              This function maps the provided slave address to a host address
756  *              and returns the mapped address and size.
757  *
758  *  @param      handle      Handle to the Processor object
759  *  @param      dstAddr     Return parameter: Pointer to receive the mapped
760  *                          address.
761  *  @param      srcAddr     Source address in the source address space
762  *  @param      size        Size of the region to be mapped.
763  *
764  *  @sa
765  */
766 inline
767 Int
768 Processor_map (Processor_Handle handle,
769                UInt32 *         dstAddr,
770                UInt32           nSegs,
771                Memory_SGList *  sglist)
773     Int                status     = PROCESSOR_SUCCESS;
774     Processor_Object * procHandle = (Processor_Object *) handle;
776     GT_4trace (curTrace, GT_ENTER, "Processor_map",
777                handle, dstAddr, nSegs, sglist);
779     GT_assert (curTrace, (handle  != NULL));
780     GT_assert (curTrace, (dstAddr != NULL));
781     GT_assert (curTrace, (sglist  != NULL));
782     GT_assert (curTrace, (nSegs   != 0));
784     /* No parameter validation here since this is an internal module, and
785      * validation has already happened at the ProcMgr level.
786      */
787     GT_assert (curTrace, (procHandle->procFxnTable.map != NULL));
788     status = procHandle->procFxnTable.map (handle,
789                                            dstAddr,
790                                            nSegs,
791                                            sglist);
792 #if !defined(IPC_BUILD_OPTIMIZE)
793     if (status < 0) {
794         GT_setFailureReason (curTrace,
795                              GT_4CLASS,
796                              "Processor_map",
797                              status,
798                              "Processor address map operation failed!");
799     }
800 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
802     GT_1trace (curTrace, GT_LEAVE, "Processor_map", status);
804     /*! @retval PROCESSOR_SUCCESS Operation successful */
805     return status;
809 /*!
810  *  @brief      Function to unmap address to slave address space.
811  *
812  *  @param      handle      Handle to the Processor object
813  *  @param      dstAddr     Return parameter: Pointer to receive the mapped
814  *                          address.
815  *  @param      size        Size of the region to be mapped.
816  *
817  *  @sa
818  */
819 inline
820 Int
821 Processor_unmap (Processor_Handle handle,
822                  UInt32           addr,
823                  UInt32           size)
825     Int                status     = PROCESSOR_SUCCESS;
826     Processor_Object * procHandle = (Processor_Object *) handle;
828     GT_3trace (curTrace, GT_ENTER, "Processor_unmap",
829                handle, addr, size);
831     GT_assert (curTrace, (handle != NULL));
832     GT_assert (curTrace, (size   != 0));
834     /* No parameter validation here since this is an internal module, and
835      * validation has already happened at the ProcMgr level.
836      */
837     GT_assert (curTrace, (procHandle->procFxnTable.unmap != NULL));
838     status = procHandle->procFxnTable.unmap (handle,
839                                              addr,
840                                              size);
841 #if !defined(IPC_BUILD_OPTIMIZE)
842     if (status < 0) {
843         GT_setFailureReason (curTrace,
844                              GT_4CLASS,
845                              "Processor_unmap",
846                              status,
847                              "Processor address unmap operation failed!");
848     }
849 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
851     GT_1trace (curTrace, GT_LEAVE, "Processor_unmap", status);
853     /*! @retval PROCESSOR_SUCCESS Operation successful */
854     return status;
858 Void
859 Processor_EventTimerExpirationFxn (union sigval val)
861     Processor_RegisterElem * elem = (Processor_RegisterElem *)val.sival_ptr;
863     /* Notify the user of the timer expiration. */
864     elem->info->cbFxn(elem->procId,
865                       NULL,
866                       ProcMgr_State_Unknown,
867                       ProcMgr_State_Unknown,
868                       ProcMgr_EventStatus_Timeout,
869                       elem->info->arg);
873 /*!
874  *  @brief      Function that registers for notification when the slave
875  *              processor transitions to any of the states specified.
876  *
877  *              This function allows the user application to register for
878  *              changes in processor state and take actions accordingly.
879  *
880  *  @param      handle      Handle to the Processor object
881  *  @param      fxn         Handling function to be registered.
882  *  @param      args        Optional arguments associated with the handler fxn.
883  *  @param      state       Array of target states for which registration is
884  *                          required.
885  *
886  *  @sa
887  */
888 inline
889 Int
890 Processor_registerNotify (Processor_Handle    handle,
891                           ProcMgr_CallbackFxn fxn,
892                           Ptr                 args,
893                           Int                 timeout,
894                           ProcMgr_State       state [])
896     Int                      status     = PROCESSOR_SUCCESS;
897     Processor_Object       * procHandle = (Processor_Object *) handle;
898     Processor_RegisterElem * elem       = NULL;
899     Int                      i          = 0;
900     IArg                     key        = NULL;
901     pthread_attr_t           thread_attrs;
902     struct sigevent          event;
904     GT_4trace (curTrace, GT_ENTER, "Processor_registerNotify",
905                handle, fxn, args, state);
907     GT_assert (curTrace, (handle        != NULL));
908     GT_assert (curTrace, (fxn           != 0));
909     /* args is optional and may be NULL. */
911     /* No parameter validation here since this is an internal module, and
912      * validation has already happened at the ProcMgr level.
913      */
914     elem = Memory_alloc(NULL, sizeof(Processor_RegisterElem), 0, NULL);
915 #if !defined(IPC_BUILD_OPTIMIZE)
916     if (elem == NULL) {
917         /*! @retval PROCESSOR_E_FAIL Failed to configure DSP MMU. */
918         status = PROCESSOR_E_MEMORY;
919         GT_setFailureReason (curTrace,
920                              GT_4CLASS,
921                              "Processor_registerNotify",
922                              status,
923                              "Failed to allocate memory");
924     }
925     else {
926 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
927         elem->info = Memory_alloc(NULL,
928             sizeof(Processor_Register) + (sizeof(ProcMgr_State) * ProcMgr_State_EndValue),
929             0, NULL);
930 #if !defined(IPC_BUILD_OPTIMIZE)
931         if (elem->info == NULL) {
932             /*! @retval PROCESSOR_E_FAIL Failed to configure DSP MMU. */
933             status = PROCESSOR_E_MEMORY;
934             GT_setFailureReason (curTrace,
935                                  GT_4CLASS,
936                                  "Processor_registerNotify",
937                                  status,
938                                  "Failed to allocate memory");
939         }
940         else {
941 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
942             List_elemClear((List_Elem *)elem);
943             for (i = 0; state[i] != ProcMgr_State_EndValue; i++)
944                 elem->info->state[i] = state[i];
945             elem->info->state[i] = ProcMgr_State_EndValue;
946             elem->info->timeout  = timeout;
947             elem->info->cbFxn    = fxn;
948             elem->info->arg      = args;
949             elem->procId         = procHandle->procId;
950             // TODO: replace timer with OSAL timer module
951             elem->timer = -1;
953             /*
954              * If a timeout has been specified, also need to start that
955              * timer here
956              */
957             if (elem->info->timeout != -1) {
958                 // TODO: replace timer with OSAL timer module
959                 pthread_attr_init(&thread_attrs);
960                 SIGEV_THREAD_INIT (&event, Processor_EventTimerExpirationFxn, elem, &thread_attrs);
961                 pthread_attr_destroy(&thread_attrs);
962                 status = timer_create(CLOCK_REALTIME,&event,&elem->timer);
963 #if !defined(IPC_BUILD_OPTIMIZE)
964                 if (status != NULL) {
965                     /*! @retval PROCESSOR_E_FAIL Failed to create timer. */
966                     status = PROCESSOR_E_MEMORY;
967                     GT_setFailureReason (curTrace,
968                                          GT_4CLASS,
969                                          "Processor_registerNotify",
970                                          status,
971                                          "Failed to create timer");
972                 }
973             }
975             if (status >= 0) {
976 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
977                 key = OsalMutex_enter(procHandle->notifiersLock);
978                 List_enqueue(procHandle->registeredNotifiers, (List_Elem *)elem);
979                 OsalMutex_leave(procHandle->notifiersLock, key);
981                 if (elem->info->timeout != -1) {
982                     // TODO: replace timer with OSAL timer module
983                     struct itimerspec value ;
984                        value.it_value.tv_sec = elem->info->timeout / 1000;
985                     value.it_value.tv_nsec = (elem->info->timeout % 1000) * 1000;
986                     value.it_interval.tv_sec = 0;
987                     value.it_interval.tv_nsec = 0;
988                     timer_settime(elem->timer,0, &value, NULL);
989                 }
990 #if !defined(IPC_BUILD_OPTIMIZE)
991             }
992         }
993     }
994 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
996     GT_1trace (curTrace, GT_LEAVE, "Processor_registerNotify", status);
998     /*! @retval PROCESSOR_SUCCESS Operation successful */
999     return status;
1003 /*!
1004  *  @brief      Function that un-registers for notification when the slave
1005  *              processor transitions to any of the states specified.
1006  *
1007  *              This function allows the user application to un-register for
1008  *              changes in processor state and take actions accordingly.
1009  *
1010  *  @param      handle      Handle to the Processor object
1011  *  @param      fxn         Handling function to be registered.
1012  *  @param      args        Optional arguments associated with the handler fxn.
1013  *  @param      state       Array of target states for which registration is
1014  *                          required.
1015  *
1016  *  @sa
1017  */
1018 inline
1019 Int
1020 Processor_unregisterNotify (Processor_Handle    handle,
1021                             ProcMgr_CallbackFxn fxn,
1022                             Ptr                 args,
1023                             ProcMgr_State       state [])
1025     Int                status     = PROCESSOR_SUCCESS;
1026     Processor_Object * procHandle = (Processor_Object *) handle;
1027     IArg               key        = NULL;
1028     List_Elem        * elem       = NULL;
1029     Processor_RegisterElem * info = NULL;
1031     GT_4trace (curTrace, GT_ENTER, "Processor_unregisterNotify",
1032                handle, fxn, args, state);
1034     GT_assert (curTrace, (handle        != NULL));
1035     GT_assert (curTrace, (fxn           != 0));
1036     /* args is optional and may be NULL. */
1038     /* No parameter validation here since this is an internal module, and
1039      * validation has already happened at the ProcMgr level.
1040      */
1041     key = OsalMutex_enter(procHandle->notifiersLock);
1042     List_traverse(elem, procHandle->registeredNotifiers) {
1043         info = (Processor_RegisterElem *)elem;
1044         if (info->info->cbFxn == fxn &&
1045             info->info->arg == args) {
1046             // TODO: replace timer with OSAL timer module
1047             /* Check if there is an associated timer and cancel it */
1048             if (info->timer != -1) {
1049                 struct itimerspec value ;
1050                 value.it_value.tv_sec = 0;
1051                 value.it_value.tv_nsec = 0;
1052                 value.it_interval.tv_sec = 0;
1053                 value.it_interval.tv_nsec = 0;
1054                 timer_settime(info->timer, 0, &value, NULL);
1056                 timer_delete(info->timer);
1057                 info->timer = -1;
1058             }
1060             /* remove the elem and respond to the client */
1061             List_remove(procHandle->registeredNotifiers, elem);
1062             info->info->cbFxn(procHandle->procId,
1063                               NULL,
1064                               procHandle->state,
1065                               procHandle->state,
1066                               ProcMgr_EventStatus_Canceled,
1067                               info->info->arg);
1068             Memory_free(NULL, info->info, sizeof(Processor_Register));
1069             Memory_free(NULL, elem, sizeof(Processor_RegisterElem));
1070             status = PROCESSOR_SUCCESS;
1071             break;
1072         }
1073     }
1074     OsalMutex_leave(procHandle->notifiersLock, key);
1076     GT_1trace (curTrace, GT_LEAVE, "Processor_unregisterNotify", status);
1078     /*! @retval PROCESSOR_SUCCESS Operation successful */
1079     return status;
1083 #if defined (__cplusplus)
1085 #endif /* defined (__cplusplus) */