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-2012, 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(SYSLINK_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(SYSLINK_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(SYSLINK_BUILD_OPTIMIZE)
135 }
136 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
138 GT_1trace (curTrace, GT_LEAVE, "Processor_attach", status);
140 /*! @retval PROCESSOR_SUCCESS Operation successful */
141 return status;
142 }
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)
163 {
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(SYSLINK_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(SYSLINK_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(SYSLINK_BUILD_OPTIMIZE)
191 }
192 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
194 GT_1trace (curTrace, GT_LEAVE, "Processor_detach", status);
196 /*! @retval PROCESSOR_SUCCESS Operation successful */
197 return status;
198 }
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)
221 {
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(SYSLINK_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(SYSLINK_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(SYSLINK_BUILD_OPTIMIZE)
252 }
253 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
255 GT_1trace (curTrace, GT_LEAVE, "Processor_start", status);
257 /*! @retval PROCESSOR_SUCCESS Operation successful */
258 return status;
259 }
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)
278 {
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(SYSLINK_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(SYSLINK_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(SYSLINK_BUILD_OPTIMIZE)
315 }
316 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
318 GT_1trace (curTrace, GT_LEAVE, "Processor_stop", status);
320 /*! @retval PROCESSOR_SUCCESS Operation successful */
321 return status;
322 }
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)
357 {
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(SYSLINK_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(SYSLINK_BUILD_OPTIMIZE) */
383 GT_1trace (curTrace, GT_LEAVE, "Processor_read", status);
385 /*! @retval PROCESSOR_SUCCESS Operation successful */
386 return status;
387 }
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)
422 {
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(SYSLINK_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(SYSLINK_BUILD_OPTIMIZE) */
451 GT_1trace (curTrace, GT_LEAVE, "Processor_write", status);
453 /*! @retval PROCESSOR_SUCCESS Operation successful */
454 return status;
455 }
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)
472 {
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;
487 }
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)
506 {
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");
556 }
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)
575 {
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");
599 }
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)
621 {
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(SYSLINK_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(SYSLINK_BUILD_OPTIMIZE) */
645 GT_1trace (curTrace, GT_LEAVE, "Processor_control", status);
647 /*! @retval PROCESSOR_SUCCESS Operation successful */
648 return status;
649 }
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)
667 {
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(SYSLINK_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(SYSLINK_BUILD_OPTIMIZE) */
694 GT_1trace (curTrace, GT_LEAVE, "Processor_translateAddr", status);
696 /*! @retval PROCESSOR_SUCCESS Operation successful */
697 return status;
698 }
701 /*!
702 * @brief Function to map address to slave address space.
703 *
704 * This function maps the provided slave address to a host address
705 * and returns the mapped address and size.
706 *
707 * @param handle Handle to the Processor object
708 * @param dstAddr Return parameter: Pointer to receive the mapped
709 * address.
710 * @param srcAddr Source address in the source address space
711 * @param size Size of the region to be mapped.
712 *
713 * @sa
714 */
715 inline
716 Int
717 Processor_map (Processor_Handle handle,
718 UInt32 * dstAddr,
719 UInt32 nSegs,
720 Memory_SGList * sglist)
721 {
722 Int status = PROCESSOR_SUCCESS;
723 Processor_Object * procHandle = (Processor_Object *) handle;
725 GT_4trace (curTrace, GT_ENTER, "Processor_map",
726 handle, dstAddr, nSegs, sglist);
728 GT_assert (curTrace, (handle != NULL));
729 GT_assert (curTrace, (dstAddr != NULL));
730 GT_assert (curTrace, (sglist != NULL));
731 GT_assert (curTrace, (nSegs != 0));
733 /* No parameter validation here since this is an internal module, and
734 * validation has already happened at the ProcMgr level.
735 */
736 GT_assert (curTrace, (procHandle->procFxnTable.map != NULL));
737 status = procHandle->procFxnTable.map (handle,
738 dstAddr,
739 nSegs,
740 sglist);
741 #if !defined(SYSLINK_BUILD_OPTIMIZE)
742 if (status < 0) {
743 GT_setFailureReason (curTrace,
744 GT_4CLASS,
745 "Processor_map",
746 status,
747 "Processor address map operation failed!");
748 }
749 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
751 GT_1trace (curTrace, GT_LEAVE, "Processor_map", status);
753 /*! @retval PROCESSOR_SUCCESS Operation successful */
754 return status;
755 }
758 /*!
759 * @brief Function to unmap address to slave address space.
760 *
761 * @param handle Handle to the Processor object
762 * @param dstAddr Return parameter: Pointer to receive the mapped
763 * address.
764 * @param size Size of the region to be mapped.
765 *
766 * @sa
767 */
768 inline
769 Int
770 Processor_unmap (Processor_Handle handle,
771 UInt32 addr,
772 UInt32 size)
773 {
774 Int status = PROCESSOR_SUCCESS;
775 Processor_Object * procHandle = (Processor_Object *) handle;
777 GT_3trace (curTrace, GT_ENTER, "Processor_unmap",
778 handle, addr, size);
780 GT_assert (curTrace, (handle != NULL));
781 GT_assert (curTrace, (size != 0));
783 /* No parameter validation here since this is an internal module, and
784 * validation has already happened at the ProcMgr level.
785 */
786 GT_assert (curTrace, (procHandle->procFxnTable.unmap != NULL));
787 status = procHandle->procFxnTable.unmap (handle,
788 addr,
789 size);
790 #if !defined(SYSLINK_BUILD_OPTIMIZE)
791 if (status < 0) {
792 GT_setFailureReason (curTrace,
793 GT_4CLASS,
794 "Processor_unmap",
795 status,
796 "Processor address unmap operation failed!");
797 }
798 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
800 GT_1trace (curTrace, GT_LEAVE, "Processor_unmap", status);
802 /*! @retval PROCESSOR_SUCCESS Operation successful */
803 return status;
804 }
807 Void
808 Processor_EventTimerExpirationFxn (union sigval val)
809 {
810 Processor_RegisterElem * elem = (Processor_RegisterElem *)val.sival_ptr;
812 /* Notify the user of the timer expiration. */
813 elem->info->cbFxn(elem->procId,
814 NULL,
815 ProcMgr_State_Unknown,
816 ProcMgr_State_Unknown,
817 ProcMgr_EventStatus_Timeout,
818 elem->info->arg);
819 }
822 /*!
823 * @brief Function that registers for notification when the slave
824 * processor transitions to any of the states specified.
825 *
826 * This function allows the user application to register for
827 * changes in processor state and take actions accordingly.
828 *
829 * @param handle Handle to the Processor object
830 * @param fxn Handling function to be registered.
831 * @param args Optional arguments associated with the handler fxn.
832 * @param state Array of target states for which registration is
833 * required.
834 *
835 * @sa
836 */
837 inline
838 Int
839 Processor_registerNotify (Processor_Handle handle,
840 ProcMgr_CallbackFxn fxn,
841 Ptr args,
842 Int timeout,
843 ProcMgr_State state [])
844 {
845 Int status = PROCESSOR_SUCCESS;
846 Processor_Object * procHandle = (Processor_Object *) handle;
847 Processor_RegisterElem * elem = NULL;
848 Int i = 0;
849 IArg key = NULL;
850 pthread_attr_t thread_attrs;
851 struct sigevent event;
853 GT_4trace (curTrace, GT_ENTER, "Processor_registerNotify",
854 handle, fxn, args, state);
856 GT_assert (curTrace, (handle != NULL));
857 GT_assert (curTrace, (fxn != 0));
858 /* args is optional and may be NULL. */
860 /* No parameter validation here since this is an internal module, and
861 * validation has already happened at the ProcMgr level.
862 */
863 elem = Memory_alloc(NULL, sizeof(Processor_RegisterElem), 0, NULL);
864 #if !defined(SYSLINK_BUILD_OPTIMIZE)
865 if (elem == NULL) {
866 /*! @retval PROCESSOR_E_FAIL Failed to configure DSP MMU. */
867 status = PROCESSOR_E_MEMORY;
868 GT_setFailureReason (curTrace,
869 GT_4CLASS,
870 "Processor_registerNotify",
871 status,
872 "Failed to allocate memory");
873 }
874 else {
875 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
876 elem->info = Memory_alloc(NULL,
877 sizeof(Processor_Register) + (sizeof(ProcMgr_State) * ProcMgr_State_EndValue),
878 0, NULL);
879 #if !defined(SYSLINK_BUILD_OPTIMIZE)
880 if (elem->info == NULL) {
881 /*! @retval PROCESSOR_E_FAIL Failed to configure DSP MMU. */
882 status = PROCESSOR_E_MEMORY;
883 GT_setFailureReason (curTrace,
884 GT_4CLASS,
885 "Processor_registerNotify",
886 status,
887 "Failed to allocate memory");
888 }
889 else {
890 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
891 List_elemClear((List_Elem *)elem);
892 for (i = 0; state[i] != ProcMgr_State_EndValue; i++)
893 elem->info->state[i] = state[i];
894 elem->info->state[i] = ProcMgr_State_EndValue;
895 elem->info->timeout = timeout;
896 elem->info->cbFxn = fxn;
897 elem->info->arg = args;
898 elem->procId = procHandle->procId;
899 // TODO: replace timer with OSAL timer module
900 elem->timer = -1;
902 /*
903 * If a timeout has been specified, also need to start that
904 * timer here
905 */
906 if (elem->info->timeout != -1) {
907 // TODO: replace timer with OSAL timer module
908 pthread_attr_init(&thread_attrs);
909 SIGEV_THREAD_INIT (&event, Processor_EventTimerExpirationFxn, elem, &thread_attrs);
910 pthread_attr_destroy(&thread_attrs);
911 status = timer_create(CLOCK_REALTIME,&event,&elem->timer);
912 #if !defined(SYSLINK_BUILD_OPTIMIZE)
913 if (status != NULL) {
914 /*! @retval PROCESSOR_E_FAIL Failed to create timer. */
915 status = PROCESSOR_E_MEMORY;
916 GT_setFailureReason (curTrace,
917 GT_4CLASS,
918 "Processor_registerNotify",
919 status,
920 "Failed to create timer");
921 }
922 }
924 if (status >= 0) {
925 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
926 key = OsalMutex_enter(procHandle->notifiersLock);
927 List_enqueue(procHandle->registeredNotifiers, (List_Elem *)elem);
928 OsalMutex_leave(procHandle->notifiersLock, key);
930 if (elem->info->timeout != -1) {
931 // TODO: replace timer with OSAL timer module
932 struct itimerspec value ;
933 value.it_value.tv_sec = elem->info->timeout / 1000;
934 value.it_value.tv_nsec = (elem->info->timeout % 1000) * 1000;
935 value.it_interval.tv_sec = 0;
936 value.it_interval.tv_nsec = 0;
937 timer_settime(elem->timer,0, &value, NULL);
938 }
939 #if !defined(SYSLINK_BUILD_OPTIMIZE)
940 }
941 }
942 }
943 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
945 GT_1trace (curTrace, GT_LEAVE, "Processor_registerNotify", status);
947 /*! @retval PROCESSOR_SUCCESS Operation successful */
948 return status;
949 }
952 /*!
953 * @brief Function that un-registers for notification when the slave
954 * processor transitions to any of the states specified.
955 *
956 * This function allows the user application to un-register for
957 * changes in processor state and take actions accordingly.
958 *
959 * @param handle Handle to the Processor object
960 * @param fxn Handling function to be registered.
961 * @param args Optional arguments associated with the handler fxn.
962 * @param state Array of target states for which registration is
963 * required.
964 *
965 * @sa
966 */
967 inline
968 Int
969 Processor_unregisterNotify (Processor_Handle handle,
970 ProcMgr_CallbackFxn fxn,
971 Ptr args,
972 ProcMgr_State state [])
973 {
974 Int status = PROCESSOR_SUCCESS;
975 Processor_Object * procHandle = (Processor_Object *) handle;
976 IArg key = NULL;
977 List_Elem * elem = NULL;
978 Processor_RegisterElem * info = NULL;
980 GT_4trace (curTrace, GT_ENTER, "Processor_unregisterNotify",
981 handle, fxn, args, state);
983 GT_assert (curTrace, (handle != NULL));
984 GT_assert (curTrace, (fxn != 0));
985 /* args is optional and may be NULL. */
987 /* No parameter validation here since this is an internal module, and
988 * validation has already happened at the ProcMgr level.
989 */
990 key = OsalMutex_enter(procHandle->notifiersLock);
991 List_traverse(elem, procHandle->registeredNotifiers) {
992 info = (Processor_RegisterElem *)elem;
993 if (info->info->cbFxn == fxn &&
994 info->info->arg == args) {
995 // TODO: replace timer with OSAL timer module
996 /* Check if there is an associated timer and cancel it */
997 if (info->timer != -1) {
998 struct itimerspec value ;
999 value.it_value.tv_sec = 0;
1000 value.it_value.tv_nsec = 0;
1001 value.it_interval.tv_sec = 0;
1002 value.it_interval.tv_nsec = 0;
1003 timer_settime(info->timer, 0, &value, NULL);
1005 timer_delete(info->timer);
1006 info->timer = -1;
1007 }
1009 /* remove the elem and respond to the client */
1010 List_remove(procHandle->registeredNotifiers, elem);
1011 info->info->cbFxn(procHandle->procId,
1012 NULL,
1013 procHandle->state,
1014 procHandle->state,
1015 ProcMgr_EventStatus_Canceled,
1016 info->info->arg);
1017 Memory_free(NULL, info->info, sizeof(Processor_Register));
1018 Memory_free(NULL, elem, sizeof(Processor_RegisterElem));
1019 status = PROCESSOR_SUCCESS;
1020 break;
1021 }
1022 }
1023 OsalMutex_leave(procHandle->notifiersLock, key);
1025 GT_1trace (curTrace, GT_LEAVE, "Processor_unregisterNotify", status);
1027 /*! @retval PROCESSOR_SUCCESS Operation successful */
1028 return status;
1029 }
1032 #if defined (__cplusplus)
1033 }
1034 #endif /* defined (__cplusplus) */