From 7fc919b3dd9f9817ed835f2f3e19145a9e251903 Mon Sep 17 00:00:00 2001

---
 dsplink/dsp/inc/dsplink.h                    |   41 +++++++++
 dsplink/dsp/src/base/drv/dsplink.c           |   28 ++++++
 dsplink/gpp/inc/sys/Linux/drvdefs.h          |  126 ++++++++++++++------------
 dsplink/gpp/inc/sys/terminate.h              |   43 +++++++++
 dsplink/gpp/inc/usr/dsplink.h                |   16 ++++
 dsplink/gpp/inc/usr/proc.h                   |   28 ++++++
 dsplink/gpp/src/api/Linux/drv_api.c          |   65 ++++++++++++-
 dsplink/gpp/src/api/proc.c                   |   41 +++++++++
 dsplink/gpp/src/api/ringio.c                 |   16 ++--
 dsplink/gpp/src/osal/osal.c                  |    4 +-
 dsplink/gpp/src/osal/osal.h                  |    6 +-
 dsplink/gpp/src/pmgr/Linux/2.6.18/drv_pmgr.c |   84 ++++++++++++++++-
 dsplink/gpp/src/pmgr/pmgr_proc.c             |   37 +++++++-
 dsplink/gpp/src/pmgr/pmgr_proc.h             |   22 +++++
 14 files changed, 481 insertions(+), 76 deletions(-)
 create mode 100644 dsplink/gpp/inc/sys/terminate.h

diff --git dsplink/dsp/inc/dsplink.h dsplink/dsp/inc/dsplink.h
index 992643e..506d500 100644
--- dsplink/dsp/inc/dsplink.h
+++ dsplink/dsp/inc/dsplink.h
@@ -89,6 +89,47 @@ extern "C" {
  */
 #define  MAX_IPS              16
 
+/*  ============================================================================
+ *  @const  DSPLINK_TERMINATE_EVT
+ *
+ *  @desc   The event number (0 - 31) to use for the DSPLink terminate event.
+ *          This must match with dsplink/gpp/inc/usr/dsplink.h. The default
+ *          value (-1) disables the terminate event signaling. Modify this
+ *          definition to enable the feature and to specify the terminate
+ *          event number.
+ *
+ *          Example usage to enable terminate event.
+ *
+ *          #define DSPLINK_TERMINATE_EVT 28
+ *  ============================================================================
+ */
+#define DSPLINK_TERMINATE_EVT (-1)
+
+/*  ============================================================================
+ *  @name   DSPLINK_TerminateFxn
+ *
+ *  @desc   Function prototype for the DSPLink terminate handler function.
+ *  ============================================================================
+ */
+typedef Void (*DSPLINK_TerminateFxn)(Void);
+
+/*  ============================================================================
+ *  @name   DSPLINK_terminateFxn
+ *
+ *  @desc   Global symbol used by client to register an application specific
+ *          terminate handler function. This function is invoked in interrupt
+ *          context, it must obay all runtime context rules. Use this function
+ *          to post a BIOS SWI or TSK function if needed.
+ *
+ *          Example usage (suggested for main()).
+ *
+ *          #include <dsplink.h>
+ *          Void DSP_terminateFxn(Void) { ... }
+ *          DSPLINK_terminateFxn = DSP_terminateFxn;  // do this  in main
+ *  ============================================================================
+ */
+extern far DSPLINK_TerminateFxn DSPLINK_terminateFxn;
+
 #if defined (POOL_COMPONENT)
 /** ============================================================================
  *  @name   MAX_POOLENTRIES
diff --git dsplink/dsp/src/base/drv/dsplink.c dsplink/dsp/src/base/drv/dsplink.c
index 2ee3932..9c8e828 100644
--- dsplink/dsp/src/base/drv/dsplink.c
+++ dsplink/dsp/src/base/drv/dsplink.c
@@ -53,6 +53,7 @@
 #include <dbc.h>
 #include <hal.h>
 #include <hal_cache.h>
+#include <ips.h>
 #include <_dsplink.h>
 #include <shm_drv.h>
 #include <dsplinkips.h>
@@ -130,6 +131,14 @@ Uint8  DSPLINK_shmBaseAddress_pad[CACHE_L2_LINESIZE- sizeof(Uint32)] ;
  */
 static Bool DSPLINK_isInitialized = FALSE ;
 
+/** ----------------------------------------------------------------------------
+ *  @name   DSPLINK_terminateFxn
+ *
+ *  @desc   Contains application specific terminate function address.
+ *  ----------------------------------------------------------------------------
+ */
+DSPLINK_TerminateFxn DSPLINK_terminateFxn = NULL;
+
 /** ============================================================================
  *  Create named sections for all DSPLINK functions to allow specific memory
  *  placement.
@@ -146,6 +155,20 @@ static Bool DSPLINK_isInitialized = FALSE ;
  */
 #define NUM_CHARS_VERSION       4
 
+/** ============================================================================
+ *  @func   DSPLINK_terminateISR
+ *
+ *  @desc   IPS callback function to invoke terminate event handler.
+ *  ============================================================================
+ */
+/* ARGSUSED */
+Void DSPLINK_terminateISR(Uint32 eventNum, Ptr arg, Ptr info)
+{
+    /* invoke terminate event handler */
+    if (DSPLINK_terminateFxn != NULL) {
+        (*DSPLINK_terminateFxn)();
+    }
+}
 
 /** ============================================================================
  *  @func   DSPLINK_init
@@ -192,6 +215,11 @@ DSPLINK_init  (Void)
      * GPP, even if they are not included by the application.
      */
     SHMDRV_handshake (ID_GPP, dspHandshake) ;
+
+#if DSPLINK_TERMINATE_EVT != (-1)
+    /* register terminate event isr */
+    IPS_register(ID_GPP, 0, DSPLINK_TERMINATE_EVT, DSPLINK_terminateISR, NULL);
+#endif
 }
 
 
diff --git dsplink/gpp/inc/sys/Linux/drvdefs.h dsplink/gpp/inc/sys/Linux/drvdefs.h
index 5b25f62..5d0df07 100644
--- dsplink/gpp/inc/sys/Linux/drvdefs.h
+++ dsplink/gpp/inc/sys/Linux/drvdefs.h
@@ -157,35 +157,39 @@ extern "C" {
                                             BASE_CMD + 13u,\
                                             CMD_Args)
 
-#define CMD_PROC_ISLASTDESTROY             _IOWR(GROUP_BASE_CMD,\
+#define CMD_PROC_SENDTERMEVT               _IOWR(GROUP_BASE_CMD,\
                                             BASE_CMD + 14u,\
                                             CMD_Args)
 
-#define CMD_PROC_ISLASTDETACH              _IOWR(GROUP_BASE_CMD,\
+#define CMD_PROC_ISLASTDESTROY             _IOWR(GROUP_BASE_CMD,\
                                             BASE_CMD + 15u,\
                                             CMD_Args)
 
+#define CMD_PROC_ISLASTDETACH              _IOWR(GROUP_BASE_CMD,\
+                                            BASE_CMD + 16u,\
+                                            CMD_Args)
+
 
 #if defined (DDSP_PROFILE)
 #define CMD_PROC_INSTRUMENT                _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 16u,\
+                                            BASE_CMD + 17u,\
                                             CMD_Args)
 
 #endif
 
 #if defined (DDSP_DEBUG)
 #define CMD_PROC_DEBUG                     _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 17u,\
+                                            BASE_CMD + 18u,\
                                             CMD_Args)
 
 #endif
 
 #define CMD_PROC_CLEANUP                   _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 18u,\
+                                            BASE_CMD + 19u,\
                                             CMD_Args)
 
 #define CMD_PROC_ADDRTRANSLATE             _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 19u,\
+                                            BASE_CMD + 20u,\
                                             CMD_Args)
 
 
@@ -198,46 +202,46 @@ extern "C" {
  *  ============================================================================
  */
 #define CMD_CHNL_CREATE                    _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 20u,\
+                                            BASE_CMD + 21u,\
                                             CMD_Args)
 
 #define CMD_CHNL_DELETE                    _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 21u,\
+                                            BASE_CMD + 22u,\
                                             CMD_Args)
 
 #define CMD_CHNL_ISSUE                     _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 22u,\
+                                            BASE_CMD + 23u,\
                                             CMD_Args)
 
 #define CMD_CHNL_RECLAIM                   _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 23u,\
+                                            BASE_CMD + 24u,\
                                             CMD_Args)
 
 #define CMD_CHNL_ALLOCATEBUFFER            _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 24u,\
+                                            BASE_CMD + 25u,\
                                             CMD_Args)
 
 #define CMD_CHNL_FREEBUFFER                _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 25u,\
+                                            BASE_CMD + 26u,\
                                             CMD_Args)
 
 #define CMD_CHNL_IDLE                      _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 26u,\
+                                            BASE_CMD + 27u,\
                                             CMD_Args)
 
 #define CMD_CHNL_FLUSH                     _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 27u,\
+                                            BASE_CMD + 28u,\
                                             CMD_Args)
 
 #define CMD_CHNL_CONTROL                   _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 28u,\
+                                            BASE_CMD + 29u,\
                                             CMD_Args)
 
 
 
 #if defined (DDSP_PROFILE)
 #define CMD_CHNL_INSTRUMENT                _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 29u,\
+                                            BASE_CMD + 30u,\
                                             CMD_Args)
 
 #endif /* if defined (DDSP_PROFILE) */
@@ -245,7 +249,7 @@ extern "C" {
 
 #if defined (DDSP_DEBUG)
 #define CMD_CHNL_DEBUG                     _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 30u,\
+                                            BASE_CMD + 31u,\
                                             CMD_Args)
 
 #endif /* if defined (DDSP_DEBUG) */
@@ -260,7 +264,7 @@ extern "C" {
  */
 #if defined (CHNL_COMPONENT)
 #define CMD_DRV_GETCHNLMAPTABLE_ADDRESS    _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 31u,\
+                                            BASE_CMD + 32u,\
                                             CMD_Args)
 
 #endif /* if defined (CHNL_COMPONENT) */
@@ -274,62 +278,62 @@ extern "C" {
  *  ============================================================================
  */
 #define CMD_MSGQ_TRANSPORTOPEN             _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 32u,\
+                                            BASE_CMD + 33u,\
                                             CMD_Args)
 
 #define CMD_MSGQ_TRANSPORTCLOSE            _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 33u,\
+                                            BASE_CMD + 34u,\
                                             CMD_Args)
 
 #define CMD_MSGQ_OPEN                      _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 34u,\
+                                            BASE_CMD + 35u,\
                                             CMD_Args)
 
 #define CMD_MSGQ_CLOSE                     _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 35u,\
+                                            BASE_CMD + 36u,\
                                             CMD_Args)
 
 #define CMD_MSGQ_LOCATE                    _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 36u,\
+                                            BASE_CMD + 37u,\
                                             CMD_Args)
 
 #define CMD_MSGQ_LOCATEASYNC               _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 37u,\
+                                            BASE_CMD + 38u,\
                                             CMD_Args)
 
 #define CMD_MSGQ_RELEASE                   _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 38u,\
+                                            BASE_CMD + 39u,\
                                             CMD_Args)
 
 #define CMD_MSGQ_ALLOC                     _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 39u,\
+                                            BASE_CMD + 40u,\
                                             CMD_Args)
 
 #define CMD_MSGQ_FREE                      _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 40u,\
+                                            BASE_CMD + 41u,\
                                             CMD_Args)
 
 #define CMD_MSGQ_PUT                       _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 41u,\
+                                            BASE_CMD + 42u,\
                                             CMD_Args)
 
 #define CMD_MSGQ_GET                       _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 42u,\
+                                            BASE_CMD + 43u,\
                                             CMD_Args)
 
 #define CMD_MSGQ_SETERRORHANDLER           _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 43u,\
+                                            BASE_CMD + 44u,\
                                             CMD_Args)
 
 #define CMD_MSGQ_COUNT                     _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 44u,\
+                                            BASE_CMD + 45u,\
                                             CMD_Args)
 
 
 
 #if defined (DDSP_PROFILE)
 #define CMD_MSGQ_INSTRUMENT                _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 45u,\
+                                            BASE_CMD + 46u,\
                                             CMD_Args)
 
 #endif /* if defined (DDSP_PROFILE) */
@@ -337,7 +341,7 @@ extern "C" {
 
 #if defined (DDSP_DEBUG)
 #define CMD_MSGQ_DEBUG                     _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 46u,\
+                                            BASE_CMD + 47u,\
                                             CMD_Args)
 
 #endif /* if defined (DDSP_DEBUG) */
@@ -352,35 +356,35 @@ extern "C" {
  *  ============================================================================
  */
 #define CMD_POOL_OPEN                      _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 47u,\
+                                            BASE_CMD + 48u,\
                                             CMD_Args)
 
 #define CMD_POOL_CLOSE                     _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 48u,\
+                                            BASE_CMD + 49u,\
                                             CMD_Args)
 
 #define CMD_POOL_ALLOC                     _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 49u,\
+                                            BASE_CMD + 50u,\
                                             CMD_Args)
 
 #define CMD_POOL_FREE                      _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 50u,\
+                                            BASE_CMD + 51u,\
                                             CMD_Args)
 
 #define CMD_POOL_TRANSLATEADDR             _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 51u,\
+                                            BASE_CMD + 52u,\
                                             CMD_Args)
 
 #define CMD_POOL_RECONFIGURE               _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 52u,\
+                                            BASE_CMD + 53u,\
                                             CMD_Args)
 
 #define CMD_POOL_WRITEBACK                 _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 53u,\
+                                            BASE_CMD + 54u,\
                                             CMD_Args)
 
 #define CMD_POOL_INVALIDATE                _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 54u,\
+                                            BASE_CMD + 55u,\
                                             CMD_Args)
 
 
@@ -392,11 +396,11 @@ extern "C" {
  *  ============================================================================
  */
 #define CMD_MPCS_MAPREGION                 _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 55u,\
+                                            BASE_CMD + 56u,\
                                             CMD_Args)
 
 #define CMD_MPCS_UNMAPREGION               _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 56u,\
+                                            BASE_CMD + 57u,\
                                             CMD_Args)
 
 #endif /* if defined (MPCS_COMPONENT) */
@@ -408,29 +412,29 @@ extern "C" {
  *  ============================================================================
  */
 #define CMD_NOTIFY_INITIALIZE              _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 57u,\
+                                            BASE_CMD + 58u,\
                                             CMD_Args)
 
 #define CMD_NOTIFY_FINALIZE                _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 58u,\
+                                            BASE_CMD + 59u,\
                                             CMD_Args)
 
 #define CMD_NOTIFY_REGISTER                _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 59u,\
+                                            BASE_CMD + 60u,\
                                             CMD_Args)
 
 #define CMD_NOTIFY_UNREGISTER              _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 60u,\
+                                            BASE_CMD + 61u,\
                                             CMD_Args)
 
 #define CMD_NOTIFY_NOTIFY                  _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 61u,\
+                                            BASE_CMD + 62u,\
                                             CMD_Args)
 
 
 #if defined (DDSP_PROFILE)
 #define CMD_NOTIFY_INSTRUMENT              _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 62u,\
+                                            BASE_CMD + 63u,\
                                             CMD_Args)
 
 #endif
@@ -442,11 +446,11 @@ extern "C" {
  *  ============================================================================
  */
 #define CMD_RINGIO_MAPREGION               _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 63u,\
+                                            BASE_CMD + 64u,\
                                             CMD_Args)
 
 #define CMD_RINGIO_UNMAPREGION             _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 64u,\
+                                            BASE_CMD + 65u,\
                                             CMD_Args)
 
 
@@ -457,11 +461,11 @@ extern "C" {
  *  ============================================================================
  */
 #define CMD_MPLIST_MAPREGION               _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 65u,\
+                                            BASE_CMD + 66u,\
                                             CMD_Args)
 
 #define CMD_MPLIST_UNMAPREGION             _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 66u,\
+                                            BASE_CMD + 67u,\
                                             CMD_Args)
 
 
@@ -472,27 +476,27 @@ extern "C" {
  *  ============================================================================
  */
 #define CMD_IDM_INIT                       _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 67u,\
+                                            BASE_CMD + 68u,\
                                             CMD_Args)
 
 #define CMD_IDM_EXIT                       _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 68u,\
+                                            BASE_CMD + 69u,\
                                             CMD_Args)
 
 #define CMD_IDM_CREATE                     _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 69u,\
+                                            BASE_CMD + 70u,\
                                             CMD_Args)
 
 #define CMD_IDM_DELETE                     _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 70u,\
+                                            BASE_CMD + 71u,\
                                             CMD_Args)
 
 #define CMD_IDM_ACQUIREID                  _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 71u,\
+                                            BASE_CMD + 72u,\
                                             CMD_Args)
 
 #define CMD_IDM_RELEASEID                  _IOWR(GROUP_BASE_CMD,\
-                                            BASE_CMD + 72u,\
+                                            BASE_CMD + 73u,\
                                             CMD_Args)
 
 
@@ -559,6 +563,10 @@ typedef struct CMD_Args_tag {
         } procGetSymbolAddressArgs ;
 
         struct {
+            ProcessorId     procId;
+        } procSendTermEvtArgs;
+
+        struct {
             ProcessorId     procId ;
             PROC_Attrs *    attr   ;
         } procAttachArgs ;
diff --git dsplink/gpp/inc/sys/terminate.h dsplink/gpp/inc/sys/terminate.h
new file mode 100644
index 0000000..0c57b7d
--- /dev/null
+++ dsplink/gpp/inc/sys/terminate.h
@@ -0,0 +1,43 @@
+/** ============================================================================
+ *  @file   terminate.h
+ *
+ *  @path   $(DSPLINK)\gpp\inc\sys
+ *
+ *  @desc   Driver functions for terminate support
+ *
+ *  @rev    1
+ *  ============================================================================
+ *  Copyright (c) Texas Instruments Incorporated 2012
+ *
+ *  Use of this software is controlled by the terms and conditions found in the
+ *  license agreement under which this software has been supplied or provided.
+ *  ============================================================================
+ *  Revision History
+ *
+ *  JUL 13, 2012    TYP=ORG             REF=            Ramsey Harris
+ *      Original Version.
+ *  ============================================================================
+ */
+
+#ifndef dsplink_gpp_inc_sys_terminate_h
+#define dsplink_gpp_inc_sys_terminate_h
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/*
+ *  ======== DSPLINK_sendTerminateEvent ========
+ *  @func   DSPLINK_sendTerminateEvent
+ *
+ *  @desc   Send a terminate event to DSP if possible.
+ */
+void DSPLINK_sendTerminateEvent(void);
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* dsplink_gpp_inc_sys_terminate_h */
diff --git dsplink/gpp/inc/usr/dsplink.h dsplink/gpp/inc/usr/dsplink.h
index e0f6cf8..0699731 100644
--- dsplink/gpp/inc/usr/dsplink.h
+++ dsplink/gpp/inc/usr/dsplink.h
@@ -66,6 +66,22 @@ extern "C" {
  */
 #define MAX_IPS             16u
 
+/*  ============================================================================
+ *  @const  DSPLINK_TERMINATE_EVT
+ *
+ *  @desc   The event number (0 - 31) to use for the DSPLink terminate event.
+ *          This must match with dsplink/dsp/inc/dsplink.h. The default
+ *          value (-1) disables the terminate event signaling. Modify this
+ *          definition to enable the feature and to specify the terminate
+ *          event number.
+ *
+ *          Example usage to enable terminate event.
+ *
+ *          #define DSPLINK_TERMINATE_EVT 28
+ *  ============================================================================
+ */
+#define DSPLINK_TERMINATE_EVT (-1)
+
 /** ============================================================================
  *  @const  WAIT_FOREVER
  *
diff --git dsplink/gpp/inc/usr/proc.h dsplink/gpp/inc/usr/proc.h
index 7ba858d..d014f28 100644
--- dsplink/gpp/inc/usr/proc.h
+++ dsplink/gpp/inc/usr/proc.h
@@ -587,6 +587,34 @@ PROC_GetSymbolAddress (IN   ProcessorId   procId,
                        OUT  Uint32 *      dspAddr) ;
 
 
+/** ============================================================================
+ *  @func   PROC_sendTerminateEvent
+ *
+ *  @desc   Send an IPS terminate event to the DSP.
+ *
+ *  @arg    procId
+ *              DSP Identifier.
+ *
+ *  @ret    DSP_SOK
+ *              Operation successfully completed.
+ *          DSP_EFAIL
+ *              General failure.
+ *          DSP_EINVALIDARG
+ *              Given procId is invalid.   
+ *
+ *  @enter  procId must be valid.
+ *          PROC_start has been successful.
+ *
+ *  @leave  None
+ *
+ *  @see    PROC_start
+ *  ============================================================================
+ */
+EXPORT_API
+DSP_STATUS
+PROC_sendTerminateEvent(IN ProcessorId procId);
+
+
 #if defined (DDSP_PROFILE)
 /** ============================================================================
  *  @func   PROC_instrument
diff --git dsplink/gpp/src/api/Linux/drv_api.c dsplink/gpp/src/api/Linux/drv_api.c
index 7049af9..37b12cd 100644
--- dsplink/gpp/src/api/Linux/drv_api.c
+++ dsplink/gpp/src/api/Linux/drv_api.c
@@ -50,7 +50,6 @@
 #include <errno.h>
 #include <signal.h>
 #include <stdlib.h>
-#include <unistd.h>
 #include <sys/mman.h>
 #include <sys/ipc.h>
 #include <sys/sem.h>
@@ -209,6 +208,15 @@ typedef struct DRV_ProtectObject_tag {
 } DRV_ProtectObject ;
 
 /** ============================================================================
+ *  @name   DSPLINK_skipExitHandler
+ *
+ *  @desc   Global flag to indicate that exit handler has already been
+ *          called from signal handler.
+ *  ============================================================================
+ */
+Bool DSPLINK_skipExitHandler = FALSE;
+
+/** ============================================================================
  *  @name   DSPLINK_isSignal
  *
  *  @desc   Global flag to indicate whether execution is in signal context.
@@ -351,6 +359,18 @@ DRV_Initialize (OUT DRV_Object ** drvObj,     IN OUT Pvoid arg)
                 }
             }
 
+            /* Associate this process with the file object. This allows
+             * the driver to detect when the application has been terminated.
+             */
+            if (DSP_SUCCEEDED(status)) {
+                osStatus = fcntl((*drvObj)->driverHandle, F_SETOWN, getpid());
+
+                if (osStatus != 0) {
+                    status = DSP_EFAIL;
+                    SET_FAILURE_REASON;
+                }
+            }
+
 #if defined (CHNL_COMPONENT)
             if (DSP_SUCCEEDED (status)) {
                 osStatus = ioctl ((*drvObj)->driverHandle,
@@ -449,6 +469,9 @@ DRV_Finalize (IN DRV_Object * drvObj,     IN OUT Pvoid arg)
             }
 #endif /* if defined (CHNL_COMPONENT) */
 
+            /* clear process id to indicate normal shutdown to driver */
+            fcntl(drvObj->driverHandle, F_SETOWN, 0);
+
             osStatus = close (drvObj->driverHandle) ;
 
             drvObj->signature = SIGN_NULL ;
@@ -1017,6 +1040,23 @@ DRV_Invoke (IN         DRV_Object * drvObj,
             }
             break ;
 
+        case CMD_PROC_SENDTERMEVT:
+            {
+                if (DRV_handle == NULL) {
+                    status = DSP_EFAIL;
+                    SET_FAILURE_REASON;
+                }
+
+                if (DSP_SUCCEEDED(status)) {
+                    osStatus = ioctl(DRV_handle->driverHandle, cmdId, args);
+                    if (osStatus < 0) {
+                        status = DSP_EFAIL;
+                        SET_FAILURE_REASON;
+                    }
+                }
+            }
+            break ;
+
 #if defined (POOL_COMPONENT)
         case CMD_POOL_ALLOC:
             {
@@ -1634,11 +1674,18 @@ DSPLINK_atExitHandler (Void)
     int         osStatus = 0 ;
     Uint32      procId   = 0 ; /* Hard code for now. */
     CMD_Args    args ;
+    PROC_State  procState;
 #if defined (POOL_COMPONENT)
     Uint32      i ;
 #endif /* if defined (POOL_COMPONENT) */
 
     TRC_0ENTER ("DSPLINK_atExitHandler") ;
+
+    /* skip handler if already invoked by signal handler */
+    if (DSPLINK_skipExitHandler) {
+        goto leave;
+    }
+
     TRC_0PRINT (TRC_LEVEL7,
     "=====================================================================\n"
     "IMPORTANT: There may be several error prints in the atExit handler.  \n"
@@ -1655,7 +1702,19 @@ DSPLINK_atExitHandler (Void)
     MSGQ_transportClose (procId) ;
 #endif /* if defined (MSGQ_COMPONENT) */
 
-    PROC_stop (procId) ;
+#if DSPLINK_TERMINATE_EVT != (-1)
+    /* if dsp still running, send terminate event */
+    PROC_getState(procId, &procState);
+
+    if (procState == ProcState_Started) {
+        PROC_sendTerminateEvent(procId);
+    }
+    else {
+        PROC_stop(procId);
+    }
+#else
+        PROC_stop(procId);
+#endif
 
     if (DRV_handle != NULL) {
         osStatus = ioctl (DRV_handle->driverHandle, CMD_PROC_CLEANUP, &args) ;
@@ -1677,6 +1736,7 @@ DSPLINK_atExitHandler (Void)
     /* Reset the DSPLINK_isSignal flag */
     DSPLINK_isSignal = FALSE;
 
+leave:
     TRC_0LEAVE ("DSPLINK_atExitHandler") ;
 
     return ;
@@ -1712,6 +1772,7 @@ DSPLINK_sigHandler (int sigNum)
      * can be pre-empted by a signal.
      */
     DSPLINK_atExitHandler () ;
+    DSPLINK_skipExitHandler = TRUE;
 
     /*  Force hard stop on the process  */
     exit (0) ;
diff --git dsplink/gpp/src/api/proc.c dsplink/gpp/src/api/proc.c
index b148839..3b25e35 100644
--- dsplink/gpp/src/api/proc.c
+++ dsplink/gpp/src/api/proc.c
@@ -1290,6 +1290,47 @@ PROC_control (IN  ProcessorId procId,
 }
 
 
+/** ============================================================================
+ *  @func   PROC_sendTerminateEvent
+ *
+ *  @desc   Send an IPS terminate event to the DSP.
+ *
+ *  @modif  None
+ *  ============================================================================
+ */
+EXPORT_API
+DSP_STATUS
+PROC_sendTerminateEvent(IN ProcessorId procId)
+{
+    DSP_STATUS status = DSP_SOK;
+    CMD_Args args;
+
+    TRC_1ENTER("PROC_sendTerminateEvent", procId);
+
+    DBC_Require(IS_VALID_PROCID(procId));
+
+    if (IS_VALID_PROCID(procId) == FALSE) {
+        status = DSP_EINVALIDARG;
+        SET_FAILURE_REASON;
+    }
+
+    if (DSP_SUCCEEDED(status)) {
+        args.apiArgs.procSendTermEvtArgs.procId = procId;
+
+        status = DRV_INVOKE(DRV_handle, CMD_PROC_SENDTERMEVT, &args);
+
+        if (DSP_FAILED (status)) {
+            status = DSP_EFAIL;
+            SET_FAILURE_REASON;
+        }
+    }
+
+    TRC_1LEAVE("PROC_sendTerminateEvent", status);
+
+    return(status);
+}
+
+
 /** ----------------------------------------------------------------------------
  *  @func   PROC_resetCurStatus
  *
diff --git dsplink/gpp/src/api/ringio.c dsplink/gpp/src/api/ringio.c
index 2a094f1..8e11a49 100644
--- dsplink/gpp/src/api/ringio.c
+++ dsplink/gpp/src/api/ringio.c
@@ -173,12 +173,17 @@ RingIO_create (IN ProcessorId     procId,
         SET_FAILURE_REASON ;
     }
     else {
-        ringIoState = &RingIO_State [procId] ;
-        DBC_Assert (ringIoState != NULL) ;
-        if (ringIoState->ctrlPtr == NULL) {
-            status = DSP_EACCESSDENIED ;
+        if (IS_VALID_PROCID (procId) == FALSE) {
+            status = DSP_EINVALIDARG ;
             SET_FAILURE_REASON ;
         }
+        else {
+            ringIoState = &RingIO_State [procId] ;
+            if (ringIoState->ctrlPtr == NULL) {
+                status = DSP_EACCESSDENIED ;
+                SET_FAILURE_REASON ;
+            }
+        }
     }
 
     if (DSP_SUCCEEDED (status)) {
@@ -690,10 +695,9 @@ RingIO_open (IN Char8 * pName, IN RingIO_OpenMode openMode, IN Uint32 flags)
 
     if (DSP_SUCCEEDED (status)) {
         for (procId = 0 ;
-             (procId < MAX_PROCESSORS) && (control == NULL) ;
+             (procId < MAX_DSPS) && (control == NULL) ;
              procId++) {
             ringIoState = &RingIO_State [procId] ;
-            DBC_Assert (ringIoState != NULL) ;
             if (ringIoState->ctrlPtr != NULL) {
                 status = MPCS_enter (ringIoState->mpcsObj) ;
                 if (DSP_FAILED (status)) {
diff --git dsplink/gpp/src/osal/osal.c dsplink/gpp/src/osal/osal.c
index 82baba3..0533cd8 100644
--- dsplink/gpp/src/osal/osal.c
+++ dsplink/gpp/src/osal/osal.c
@@ -158,14 +158,14 @@ OSAL_Initialize (Void)
  */
 EXPORT_API
 DSP_STATUS
-OSAL_Finalize (Void)
+OSAL_Finalize (Bool forceFlag)
 {
     DSP_STATUS status    = DSP_SOK ;
     DSP_STATUS tmpStatus = DSP_SOK ;
 
     TRC_0ENTER ("OSAL_Finalize") ;
 
-    if (OSAL_InitializeCount == 1) {
+    if (OSAL_InitializeCount == 1 || forceFlag == TRUE) {
 
         status = PRINT_Finalize  () ;
         if (DSP_FAILED (status)) {
diff --git dsplink/gpp/src/osal/osal.h dsplink/gpp/src/osal/osal.h
index 4b80ba6..da57eb3 100644
--- dsplink/gpp/src/osal/osal.h
+++ dsplink/gpp/src/osal/osal.h
@@ -80,7 +80,8 @@ OSAL_Initialize (Void) ;
  *  @desc   Releases OS adaptation layer resources indicating that they would
  *          no longer be used.
  *
- *  @arg    None
+ *  @arg    forceFlag
+ *              Flag to unconditionally remove the OS adaptation resources
  *
  *  @ret    DSP_SOK
  *              Operation successfully completed.
@@ -98,7 +99,8 @@ OSAL_Initialize (Void) ;
  */
 EXPORT_API
 DSP_STATUS
-OSAL_Finalize (Void) ;
+OSAL_Finalize (Bool forceFlag) ;
+
 
 
 #if defined (__cplusplus)
diff --git dsplink/gpp/src/pmgr/Linux/2.6.18/drv_pmgr.c dsplink/gpp/src/pmgr/Linux/2.6.18/drv_pmgr.c
index 0eb622f..deb4f54 100644
--- dsplink/gpp/src/pmgr/Linux/2.6.18/drv_pmgr.c
+++ dsplink/gpp/src/pmgr/Linux/2.6.18/drv_pmgr.c
@@ -44,7 +44,7 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <asm/uaccess.h>
-
+#include <linux/pid.h>
 #include <asm/io.h>
 
 /*  ----------------------------------- DSP/BIOS Link               */
@@ -52,6 +52,7 @@
 #include <_dsplink.h>
 #include <procdefs.h>
 #include <version.h>
+#include <terminate.h>
 
 #if defined (RINGIO_COMPONENT)
 #include <ringiodefs.h>
@@ -141,6 +142,7 @@
 EXPORT_SYMBOL(LDRV_PROC_getState);
 EXPORT_SYMBOL(LDRV_PROC_setState);
 EXPORT_SYMBOL(PMGR_PROC_getSymbolAddress);
+EXPORT_SYMBOL(DSPLINK_sendTerminateEvent);
 #if !(defined (ONLY_PROC_COMPONENT))
 EXPORT_SYMBOL(IPS_register);
 EXPORT_SYMBOL(IPS_notify);
@@ -182,6 +184,14 @@ extern "C" {
  */
 STATIC Int32 major = 230 ;
 
+/** ----------------------------------------------------------------------------
+ *  @name   DRV_dspId
+ *
+ *  @desc   Local snoop value of the dsp id.
+ *  ----------------------------------------------------------------------------
+ */
+STATIC unsigned long DRV_dspId = 0xffff;
+
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
 /** ----------------------------------------------------------------------------
  *  @name   dsplink_class
@@ -740,11 +750,12 @@ void __exit DRV_FinalizeModule (void)
     UEVENT_Finalize () ;
 #endif /* #if defined (NOTIFY_COMPONENT) */
 
-    status = OSAL_Finalize () ;
+    /* Unconditional call OSAL_Finalize */
+    status = OSAL_Finalize (TRUE) ;
+
     if (DSP_FAILED (status)) {
         SET_FAILURE_REASON ;
     }
-
 }
 
 
@@ -806,7 +817,32 @@ NORMAL_API
 int
 DRV_Release (struct inode * inode, struct file * filp)
 {
-    return 0 ;
+    DSP_STATUS  status = DSP_SOK;
+
+#if DSPLINK_TERMINATE_EVT != (-1)
+    {
+        pid_t pid;
+
+        /* get the pid associated with the file pointer */
+        pid = pid_nr(filp->f_owner.pid);
+
+        /* check if application terminated and we have a valid snoop value */
+        if ((pid != 0) && (DRV_dspId != 0xffff)) {
+
+            /* send terminate event to dsp */
+            status = PMGR_PROC_sendTerminateEvent(DRV_dspId);
+
+            if (DSP_FAILED(status)) {
+                SET_FAILURE_REASON;
+            }
+
+            /* this is a one shot trigger, clear snoop value */
+            DRV_dspId = 0xffff;
+        }
+    }
+#endif
+
+    return(status);
 }
 
 
@@ -847,6 +883,13 @@ long DRV_Ioctl (struct file * filp, unsigned int cmd, unsigned long args)
                 osStatus = -1 ;
             }
         }
+
+        /* always do this regardless of previous success status */
+        if (cmd == CMD_PROC_SENDTERMEVT) {
+            /* this is a one shot trigger, clear snoop value */
+            DRV_dspId = 0xffff;
+        }
+
     }
 
     if (osStatus == 0) {
@@ -1109,6 +1152,10 @@ DRV_CallAPI (Uint32 cmd, CMD_Args * args)
 
     case CMD_PROC_START:
         retStatus = PMGR_PROC_start (args->apiArgs.procStartArgs.procId) ;
+
+        /* snoop the dsp id, used for sending terminate event */
+        DRV_dspId = args->apiArgs.procStartArgs.procId;
+
         args->apiStatus = retStatus ;
         break ;
 
@@ -1211,6 +1258,12 @@ DRV_CallAPI (Uint32 cmd, CMD_Args * args)
         args->apiStatus = retStatus ;
         break ;
 
+    case CMD_PROC_SENDTERMEVT:
+        retStatus = PMGR_PROC_sendTerminateEvent(
+                args->apiArgs.procGetSymbolAddressArgs.procId);
+        args->apiStatus = retStatus;
+        break;
+
 #if defined (DDSP_PROFILE)
     case CMD_PROC_INSTRUMENT:
         retStatus = PMGR_PROC_instrument (
@@ -1648,6 +1701,29 @@ DSPLINK_Cleanup (Void)
 #endif /* if defined (MSGQ_COMPONENT) */
 }
 
+/*
+ *  ======== DSPLINK_sendTerminateEvent ========
+ */
+
+void DSPLINK_sendTerminateEvent(void)
+{
+    DSP_STATUS  status = DSP_SOK ;
+
+    /* send terminate event if we have a valid snoop value */
+    if (DRV_dspId != 0xffff) {
+
+        /* send terminate event to dsp */
+        status = PMGR_PROC_sendTerminateEvent(DRV_dspId);
+
+        if (DSP_FAILED(status)) {
+            SET_FAILURE_REASON;
+        }
+
+        /* this is a one shot trigger, clear snoop value */
+        DRV_dspId = 0xffff;
+    }
+}
+
 
 #if defined (__cplusplus)
 }
diff --git dsplink/gpp/src/pmgr/pmgr_proc.c dsplink/gpp/src/pmgr/pmgr_proc.c
index 46e2678..98c698c 100644
--- dsplink/gpp/src/pmgr/pmgr_proc.c
+++ dsplink/gpp/src/pmgr/pmgr_proc.c
@@ -27,6 +27,9 @@
 #include <procdefs.h>
 #include <loaderdefs.h>
 #include <linkcfgdefs.h>
+#if !defined(ONLY_PROC_COMPONENT)
+#include <ips.h>
+#endif
 
 /*  ----------------------------------- Trace & Debug               */
 #include <_trace.h>
@@ -372,7 +375,7 @@ PMGR_PROC_destroy (Void)
             SET_FAILURE_REASON ;
         }
 
-        tmpStatus = OSAL_Finalize () ;
+        tmpStatus = OSAL_Finalize (FALSE) ;
         if (DSP_SUCCEEDED (status) && DSP_FAILED (tmpStatus)) {
             status = tmpStatus ;
             SET_FAILURE_REASON ;
@@ -1356,6 +1359,38 @@ PMGR_PROC_control (IN  ProcessorId procId,
 
 
 /** ============================================================================
+ *  @func   PMGR_PROC_sendTerminateEvent
+ *
+ *  @desc   Send an IPS terminate event to the DSP.
+ *
+ *  @modif  None
+ *  ============================================================================
+ */
+NORMAL_API
+DSP_STATUS
+PMGR_PROC_sendTerminateEvent(IN ProcessorId procId)
+{
+    DSP_STATUS status = DSP_SOK;
+
+    TRC_1ENTER("PMGR_PROC_sendTerminateEvent", procId);
+
+#if !defined(ONLY_PROC_COMPONENT) && (DSPLINK_TERMINATE_EVT != (-1))
+    /* send terminate event to dsp */
+    status = IPS_notify(procId, 0, DSPLINK_TERMINATE_EVT, 0, FALSE);
+
+    if (DSP_FAILED(status)) {
+        status = DSP_EFAIL;
+        SET_FAILURE_REASON;
+    }
+#endif
+
+    TRC_1LEAVE("PMGR_PROC_sendTerminateEvent", status);
+
+    return(status);
+}
+
+
+/** ============================================================================
  *  @func   PMGR_PROC_isAttached
  *
  *  @desc   Function to check whether the client identified by the specified
diff --git dsplink/gpp/src/pmgr/pmgr_proc.h dsplink/gpp/src/pmgr/pmgr_proc.h
index a0a11c2..88f769d 100644
--- dsplink/gpp/src/pmgr/pmgr_proc.h
+++ dsplink/gpp/src/pmgr/pmgr_proc.h
@@ -519,6 +519,28 @@ PMGR_PROC_control (IN  ProcessorId procId,
                    IN  Int32       cmd,
                        Pvoid       arg) ;
 
+/** ============================================================================
+ *  @func   PMGR_PROC_sendTerminateEvent
+ *
+ *  @desc   Send an IPS terminate event to the DSP.
+ *
+ *  @arg    procId
+ *              DSP Identifier.
+ *
+ *  @ret    DSP_SOK
+ *              Operation successfully completed.
+ *          DSP_EFAIL
+ *              General failure.
+ *
+ *  @enter  procId must be valid.
+ *
+ *  @leave  None
+ *  ============================================================================
+ */
+NORMAL_API
+DSP_STATUS
+PMGR_PROC_sendTerminateEvent(IN ProcessorId procId);
+
 
 /** ============================================================================
  *  @func   PMGR_PROC_isAttached
-- 
1.7.9.4

